Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 36692 | Accepted: 13368 |
Sample Inputnode
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 Outputios
3 Not Unique!
題解:
次小生成樹,維護一個兩點間的最小距離,最後再向上加
#include <stdio.h> #include <algorithm> #include <vector> #include <cstring> #include <iostream> using namespace std; #define line cout<<"------------------"<<endl; const int MAXN=1e4+10; const int INF=0x3f3f3f3f; int n,m; struct node{ int x,y; int v; bool vis; }Edge[MAXN]; bool cmp(node a,node b) { return a.v<b.v; } int pre[MAXN]; int Find(int a) { if(pre[a]==a) return a; return Find(pre[a]); } vector<int >G[110]; int maxd[110][110];//並查集劃到一個樹上後,樹上任意兩點之間的距離 void init() { for (int i = 1; i <=n; ++i) { G[i].clear(); pre[i] = i; G[i].push_back(i); } } int main() { int _; scanf("%d",&_); while(_--) { scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++) { scanf("%d%d%d",&Edge[i].x,&Edge[i].y,&Edge[i].v); Edge[i].vis=false; } sort(Edge+1,Edge+1+m,cmp); int sum=0; for (int i = 1; i <=m ; ++i) { int x=Find(Edge[i].x); int y=Find(Edge[i].y); if(x!=y) { pre[x]=y; sum+=Edge[i].v; int len1=G[x].size(); int len2=G[y].size(); for (int j = 0; j <len1 ; ++j) { for (int k = 0; k <len2 ; ++k) { maxd[G[x][j]][G[y][k]]=maxd[G[y][k]][G[x][j]]=Edge[i].v;//構建兩點間最小距離 } } int tem[110]; for (int j = 0; j <len2 ; ++j) { tem[j]=G[y][j]; } for (int j = 0; j <len1 ; ++j) { G[y].push_back(G[x][j]); } for (int j = 0; j <len2 ; ++j) { G[x].push_back(tem[j]); } Edge[i].vis=true; } } int cis=INF; for (int i = 1; i <=m ; ++i) {//從不是最小生成樹上的邊,遍歷向上加。找到次小生成樹 if(!Edge[i].vis) cis=min(cis,sum+Edge[i].v-maxd[Edge[i].x][Edge[i].y]); } if(cis>sum) printf("%d\n",sum); else printf("Not Unique!\n"); } return 0; } //poj1679