http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1541
题目大意:
大家新年快乐~
我们知道有最小生成树,这题是求比最小生成树大一点的,也就是求次小的生成树
思路:
新年第一战~1A~ 次小MST,半小时搞定~
和上一次那一次那一题一样。(点击直达:POJ 1679 The Unique 次最小生成树 MST)
先求MST然后DFS在枚举m-n+1条边。
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAXN=100+10; int n,m,vis[MAXN*MAXN],fa[MAXN],dp[MAXN][MAXN]; int head[MAXN],len; struct edge { int to,val,next; }e[MAXN*MAXN]; void add(int from,int to,int val) { e[len].to=to; e[len].val=val; e[len].next=head[from]; head[from]=len++; } struct edge2 { int from,to,val; bool operator <(const edge2& x)const { return val<x.val; } }e2[MAXN*MAXN]; int find(int cur) { return cur==fa[cur]? cur: fa[cur]=find(fa[cur]); } vector<int> nodes; void dfs(int cur,int fa,int dis) { for(int i=0;i<nodes.size();i++) { int x=nodes[i]; dp[x][cur]=dp[cur][x]=max(dp[x][fa],dis); } nodes.push_back(cur); for(int i=head[cur];i!=-1;i=e[i].next) { int id=e[i].to; if(id!=fa) dfs(id,cur,e[i].val); } } int main() { int T; scanf("%d",&T); while(T--) { memset(dp,0,sizeof(dp)); memset(head,-1,sizeof(head)); len=0; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&e2[i].from,&e2[i].to,&e2[i].val); vis[i]=false; } //kruskal int mstlen=0,mstlen2=9999999; sort(e2,e2+m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=0;i<m;i++) { int x=e2[i].from,y=e2[i].to; int root_x=find(x),root_y=find(y); if(root_x==root_y) continue; fa[root_x]=root_y; add(x,y,e2[i].val); add(y,x,e2[i].val); mstlen+=e2[i].val; vis[i]=true; } nodes.clear(); dfs(1,-1,0); for(int i=0;i<m;i++) { if(vis[i]) continue; mstlen2=min(mstlen2,mstlen-dp[ e2[i].from ][ e2[i].to ]+e2[i].val); } printf("%d %d\n",mstlen,mstlen2); } return 0; }