您的位置:首页 > 其它

poj 1679 判断最小生成树是否唯一

2013-08-19 18:47 344 查看
昨天一直WA,仔细看了下,是最小生成树的写法问题,路径记录的不正确,以后果断换种写法

我的做法是先求最小生成树,再枚举树边去掉,再求最小生成树,看是否还是相同的结果,如果是,则证明不唯一




View Code

1 #include<stdio.h>
2 #include<string.h>
3 #include<vector>
4 #define M 110
5 using namespace std;
6 vector<int> edge[110];
7 int map[110][110];
8 const int inf = 9999999;
9 int vis[110],lowc[110];
10 bool flag[M];
11 double D[M];
12 int pre[M];
13 int prime(int s,int n,bool truth)
14 {
15       int i,v,k;
16       int mi;
17       int ret=0;
18       for(i=1;i<=n;i++)
19       {
20           flag[i]=0;
21           D[i]=inf;
22           pre[i]=-1;
23       }
24       D[s]=0;
25       for(k=0;k<n;k++)
26       {
27           mi=inf;
28           for(i=1;i<=n;i++)if(!flag[i])
29           {
30               if(D[i]<mi)
31               {
32                   mi=D[i];
33                   v=i;
34               }
35           }
36           ret+=mi;
37           flag[v]=1;
38           if(truth)
39           {
40              if(pre[v]!=-1)
41              {
42               edge[pre[v]].push_back(v);
43              }
44           }
45           for(i=1;i<=n;i++)if(!flag[i])
46           {
47               if(map[v][i]<D[i])
48               {
49                   D[i]=map[v][i];
50                 if(truth)  pre[i]=v;
51               }
52           }
53       }
54       return ret;
55 }
56 int main()
57 {
58     int t,i,j;
59     int n,m,x,y,w;
60     scanf("%d",&t);
61     while(t--)
62     {
63         scanf("%d%d",&n,&m);
64         for(i=0;i<=n;i++)
65         {
66             map[i][i]=0;
67             for(j=i+1;j<=n;j++)
68                map[j][i]=map[i][j]=inf;
69         }
70         for(i=0;i<m;i++)
71         {
72             scanf("%d%d%d",&x,&y,&w);
73             map[x][y]=map[y][x]=w;
74         }
75         for(i=0;i<=n;i++)
76             edge[i].clear();
77                 int ans=prime(1,n,true);
78         int flag=0;
79         for(int s=1;s<=n;s++)
80         {
81             for(j=0;j<edge[s].size();j++)
82             {
83                 int t=edge[s][j];
84                 int tmp=map[s][t];
85                 map[s][t]=map[t][s]=inf;//去掉每一条生成树的边
86                 int temp=prime(1,n,false);
87                 map[t][s]=map[s][t]=tmp;
88                 if(temp==ans)
89                 {
90                     flag=1;
91                     break;
92                 }
93             }
94             if(flag) break;
95         }
96         if(flag) printf("Not Unique!\n");
97         else printf("%d\n",ans);
98     }
99     return 0;
100 }
101


 另一种方法,先求最小生成树,再广搜或深搜求任意两点间的最大树边,再枚举不在树上的边,判断是否存在某条不是树边的边的权值等于所连两点间的最大树边,如果有,则不唯一,因为替换之后还是最小生成树,且总权值不变




View Code

1 #include<string.h>
2 #include<stdio.h>
3 #include<vector>
4 #include<math.h>
5 #include<queue>
6 using namespace std;
7 const int M =1010;
8 const int inf = 1000000;
9 int max(int a,int b){return a>b?a:b;}
10 int min(int a,int b){return a<b?a:b;}
11 int n,k,m;
12 int used[M];
13 int di[M][M],cost[M][M];
14 vector<int> edge[M];
15 bool flag[M];
16 int D[M];
17 int pre[M];
18 int prime(int s,int n)
19 {
20     int i,v,k;
21     int mi;
22     int ret=0;
23     for(i=1;i<=n;i++)
24     {
25         flag[i]=0;
26         D[i]=inf;
27         pre[i]=-1;
28     }
29     D[s]=0;
30     for(k=0;k<n;k++)
31     {
32         mi=inf;
33         for(i=1;i<=n;i++)if(!flag[i])
34         {
35             if(D[i]<mi)
36             {
37                 mi=D[i];
38                 v=i;
39             }
40         }
41         ret+=mi;
42         flag[v]=1;
43         if(pre[v]!=-1)
44         {
45             edge[pre[v]].push_back(v);
46             edge[v].push_back(pre[v]);
47         }
48         for(i=1;i<=n;i++)if(!flag[i])
49         {
50             if(di[v][i]<D[i])
51             {
52                 D[i]=di[v][i];
53                 pre[i]=v;
54             }
55         }
56     }
57     return ret;
58 }
59 void bfs(int S)
60 {
61       int i,t;
62       queue<int> Q;
63       Q.push(S);
64       while(!Q.empty())
65       {
66           int s=Q.front();Q.pop();
67           used[s]=1;
68           for(i=0;i<edge[s].size();i++)
69           {
70               t=edge[s][i];if(used[t]) continue;
71               cost[S][t]=max(di[s][t],cost[S][s]);
72               Q.push(t);
73           }
74       }
75   }
76 int main()
77 {
78     int t,i,j;
79     int a,b,c;
80     scanf("%d",&t);
81     while(t--)
82     {
83         scanf("%d%d",&n,&m);
84         for(i=1;i<=n;i++)
85         {
86             edge[i].clear();
87             cost[i][i]=0;
88             di[i][i]=0;
89             for(j=i+1;j<=n;j++)
90             {
91                 cost[j][i]=cost[i][j]=-1;
92                 di[j][i]=di[i][j]=inf;
93             }
94         }
95         for(i=0;i<m;i++)
96         {
97             scanf("%d%d%d",&a,&b,&c);
98             di[a][b]=di[b][a]=c;
99         }
100         int mm=prime(1,n);
101         memset(used,0,sizeof(used));
102         for(i=1;i<=n;i++)
103         {
104             memset(used,0,sizeof(used));
105             bfs(i);
106         }
107         int nn=1;
108         for(i=1;i<=n;i++)
109             for(j=1;j<=n;j++)
110                 if(i!=j&&i!=pre[j]&&j!=pre[i]&&di[i][j]==cost[i][j])
111                     nn=-1;
112                 if(nn!=-1)  printf("%d\n",mm);
113                 else printf("Not Unique!\n");
114     }
115     return 0;
116 }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: