| 
 | 
 
 
发表于 2022-1-30 20:55:14
|
显示全部楼层
 
 
 
 本帖最后由 guosl 于 2022-1-30 20:56 编辑  
 
本题是一个典型的最小生成树。我应用了Kruskal算法。 
为了读取数据方便我把数据文件中的”-“改成了100000,而把”,“改成了空格。 
- /*
 
 - 答案:259679
 
 - */
 
 - #include <cstdio>
 
 - #include <vector>
 
 - #include <algorithm>
 
 - using namespace std;
 
  
- const int N = 40;
 
 - const int INF = 100000;
 
  
- struct stEdge
 
 - {
 
 -   int p1, p2;
 
 -   int nLen;
 
 -   bool operator<(const stEdge& e) const
 
 -   {
 
 -     return (nLen < e.nLen);
 
 -   }
 
 - };
 
  
- vector<stEdge> v;
 
 - int r[N];
 
  
- int findroot(int nId)
 
 - {
 
 -   if (r[nId] == nId)
 
 -     return nId;
 
 -   r[nId] = findroot(r[nId]);
 
 -   return r[nId];
 
 - }
 
  
- bool mg(int nId1, int nId2)
 
 - {
 
 -   int rd1 = findroot(nId1);
 
 -   int rd2 = findroot(nId2);
 
 -   if (rd1 == rd2)
 
 -     return false;
 
 -   if (rd1 < rd2)
 
 -     r[rd2] = rd1;
 
 -   else
 
 -     r[rd1] = rd2;
 
 -   return true;
 
 - }
 
  
- int main(void)
 
 - {
 
 -   long long nTotalLen = 0;
 
 -   for (int i = 0; i < N; ++i)
 
 -     r[i] = i;
 
 -   //读入数据
 
 -   errno_t err;
 
 -   FILE* fp = NULL;
 
 -   err = fopen_s(&fp,"p107_network.txt", "r");//打开文件
 
 -   if (err != 0)
 
 -   {
 
 -     printf_s("数据文件未打开\n");
 
 -     return 0;
 
 -   }
 
 -   for (int i = 0; i < N; ++i)
 
 -   {
 
 -     for (int j = 0; j < N; ++j)
 
 -     {
 
 -       int x = 0;
 
 -       fscanf_s(fp, "%d", &x);
 
 -       if (j > i && x != INF)
 
 -       {
 
 -         stEdge e;
 
 -         e.p1 = i;
 
 -         e.p2 = j;
 
 -         e.nLen = x;
 
 -         v.push_back(e);
 
 -         nTotalLen += x;
 
 -       }
 
 -     }
 
 -   }
 
 -   fclose(fp);
 
 -   sort(v.begin(), v.end());
 
 -   int nMinSum = 0;
 
 -   for (int i = 0; i < (int)v.size(); ++i)
 
 -   {
 
 -     if (mg(v[i].p1, v[i].p2))
 
 -       nMinSum += v[i].nLen;
 
 -   }
 
 -   printf_s("%d\n", nTotalLen - nMinSum);
 
 -   return 0;
 
 - }
 
  复制代码 |   
 
 
 
 |