原题:
The Unique MST
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8142 | Accepted: 2736 |
Description
Given a connected undirected graph, tell if its minimum spanning tree is unique.
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'.
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
The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.
Output
For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.
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的每一条边存入一个结构体node数组中,里面记录该条边的两个端点和权值。
再用枚举的方法,每次循环逐个删除图中MST的一条边,看在此情况下改图是否仍能构造出一个MST使得其cost和原MST的cost相等。相等则输出
“Not Unique!”,若循环结束均无此情况出现,则可以输出原MST的cost。
以下有两种基于prime算法的解题方法,但prime算法的处理不同,最终第一个算法AC,第二个WA了。。。囧,感兴趣的大牛可以把第二
个修改修改~~~
1.
#include "stdio.h"
#include "string.h"
#define N 110
#define M 10000
#define INF 10000000
struct node
{
int u,v,w;
}edge[M];
int map[N][N],d[M],dise[M];//dise[]数组记录每个顶点取到dis[]值时对应边的顶点
bool visit[N];
int n;
void MST_prim()
{
int i,j,now,min_node,min_edge;
int edge_num, k=0,flag=1,tflag=0;
int ans=0;
for(i=1;i<=n;i++) //第一次prime
d[i]=INF;
now=1;
for(i=1;i<n;i++)
{
d[now]=-1;
min_edge=INF;
for(j=1;j<=n;j++)
if(j!=now && d[j]>=0)
{
if(map[now][j]<d[j])
{
d[j]=map[now][j];
dise[j]=now;
}
if(d[j]<min_edge)
{
min_edge=d[j];
min_node=j;
}
}
edge[k].u=min_node; //记录原MST的边
edge[k].v=dise[min_node];
edge[k].w=map[edge[k].u][edge[k].v];
k++;
now=min_node;
ans+=min_edge;
}
edge_num=k;
for(k=0;k<edge_num;k++) //第二次prime,找其他的MST
{
map[edge[k].u][edge[k].v]=INF;
map[edge[k].v][edge[k].u]=INF;
if(i!=0)
{
map[edge[k-1].u][edge[k-1].v] = edge[k-1].w;
map[edge[k-1].v][edge[k-1].u] = edge[k-1].w;
}
for(i=1;i<=n;i++)
d[i]=INF;
int ans1=0;
now=1;
for(i=1;i<n;i++){
d[now]=-1;
min_edge=INF;
for(j = 1; j <= n; j ++)
if(j!=now && d[j]> 0){
if(map[now][j]<d[j])
d[j]=map[now][j];
if(d[j]<min_edge){
min_edge=d[j];
min_node=j;
}
}
if(min_edge==INF)
{
flag=0;
break;
}
now=min_node;
ans1+=min_edge;
}
if(flag && ans1==ans) {tflag=1;break;}
}
if(tflag) printf("Not Unique!/n");
else printf("%d/n",ans);
}
int main()
{
int t,m;
scanf("%d",&t);
for(int q=0;q<t;q++)
{
int x,y,z;
int i;
scanf("%d%d",&n,&m);
for(int j=1;j<=n;j++)
for(i=1;i<=n;i++)
{
if(i==j) map[j][i]=0;
else map[j][i]=INF;
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
map[x][y]=z;
map[y][x]=z;
}
MST_prim();
}
return 0;
}
2.
#include "stdio.h"
#include "string.h"
#define N 110
#define M 10000
#define INF 10000000
struct node
{
int u,v,w;
}edge[M];
int map[N][N],d[M],dise[M];
bool visit[N];
int n;
void MST_prim()
{
int i,j;
int k;
int all_cost=0,all_cost1;
int flag=0,edge_num=1;
for(i=1;i<n;i++) //第一次prime
{
int min=INF;
for(j=1;j<=n;j++)
if(visit[j]==false && d[j]<min) {min=d[j];k=j;}
all_cost+=min;
visit[k]=true;
for(j=1;j<=n;j++)
if(visit[j]==false && map[k][j]<d[j])
d[j]=map[k][j];
if(i==1) {edge[edge_num].u=1;edge[edge_num].v=k;edge[edge_num].w=map[edge[edge_num].u][edge[edge_num].v];}
else {edge[edge_num].u=edge[edge_num-1].v;edge[edge_num].v=k;edge[edge_num].w=map[edge[edge_num].u][edge[edge_num].v];}
edge_num++; //上面是记录MST各边的代码
}
for(int t=1;t<edge_num;t++) //第二次prime
{
all_cost1=0;
map[edge[t].u][edge[t].v]=INF;
map[edge[t].v][edge[t].u]=INF;
if(t!=1)
{
map[edge[t-1].u][edge[t-1].v]=edge[t-1].w;
map[edge[t-1].v][edge[t-1].u]=edge[t-1].w;
}
for(i=1;i<=n;i++)
d[i]=map[1][i];
memset(visit,false,sizeof(visit));
visit[1]=true;
for(i=1;i<n;i++)
{
int min=INF;
for(j=1;j<=n;j++)
if(visit[j]==false && d[j]<min) {min=d[j];k=j;}
all_cost1+=min;
visit[k]=true;
for(j=1;j<=n;j++)
if(visit[j]==false && map[k][j]<d[j])
d[j]=map[k][j];
}
if(all_cost==all_cost1) {flag=1;break;}
}
if(flag) printf("Not Unique!/n");
else
printf("%d/n",all_cost);
}
int main()
{
int t,m;
scanf("%d",&t);
for(int q=0;q<t;q++)
{
int x,y,z;
int i;
scanf("%d%d",&n,&m);
for(int j=1;j<=n;j++)
for(i=1;i<=n;i++)
{
if(i==j) map[j][i]=0;
else map[j][i]=INF;
}
for(i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
map[x][y]=z;
map[y][x]=z;
}
for(i=1;i<=n;i++)
d[i]=map[1][i];
memset(visit,false,sizeof(visit));
visit[1]=true;
MST_prim();
}
return 0;
}