http://acm.pku.edu.cn/JudgeOnline/problem?id=1679
Description
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
看到網上大家都是說求次小生成樹,對這個也不太熟,我的想法是利用MST的性質,邊數相同,MST邊中有相等邊的情況,簡單實現是先用Prim或者
kruskal算法求出一組解,並記錄所選擇的邊,爲驗證唯一直接採用刪邊法,逐條刪邊,出現相同的解則退出,得出唯一的結論則要訪問到最後一條邊
不過有個小優化是 只探查存在相同權值的邊,這樣開銷應該小很多,具體實現因爲時間的關係 現在就省了 留下某牛牛代碼以後參考:
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct
{
int x;
int y;
int w;
}edge;
edge s[10010];
int top,t[10010];
bool cmp(edge s1,edge s2)
{
return s1.w<s2.w;
}
int kruscal(int n,int m,int x)
{
int i,j,a,b,tag[110],tem,sum,k;
for(i=0;i<n;i++)
{
tag[i]=i;
}
k=1;j=0;sum=0;
while(k<n)
{
a=s[j].x-1;
b=s[j].y-1;
if(j==x)
{
j++;
continue;
}
if(tag[a]!=tag[b])
{
if(x==-1)
{
t[top]=j;
top++;
}
tem=tag[b];
k++;sum+=s[j].w;
for(i=0;i<n;i++)
{
if(tag[i]==tem)
{
tag[i]=tag[a];
}
}
}
j++;
}
return sum;
}
int main()
{
freopen("in.txt","r",stdin);
int p,n,m,l,cmin,min,i,key;
while(scanf("%d",&p)!=EOF)
{
while(p--)
{
scanf("%d%d",&n,&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].w);
}
sort(s,s+m,cmp);
/*for(i=0;i<m;i++)
{
printf(" %d ",s[i].w);
}
printf("/n");*/
top=0;
min=kruscal(n,m,-1);
key=top;
for(l=0;l<key;l++)
{
cmin=kruscal(n,m,t[l]);
if(cmin==min)
{
printf("Not Unique!/n");
break;
}
}
if(l==top&&cmin!=min)
{
printf("%d/n",min);
}
}
}
}