昨天一直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 }