ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

UVA - 10462 Is There A Second Way Left?

2020-02-29 13:56:40  阅读:210  来源: 互联网

标签:int MAX There 生成 dep Second 10462 权值 include


题意:

给你一张无向图,让你判断三种情况:1.不是连通图(无法形成生成树)2.只能生成唯一的生成树 3.能生成的生成树不唯一(有次小生成树),这种情况要求出次小生成树的边权值和。

 

思路:

比较常见的次小生成数做法:先求出最小生成树,再依次使用不在最小生成树上的边与最小生成树连接,连接后必然出现且仅出现一个环(由于生成树上的任意两点之间都有唯一的一条路径,且图中所有的点都在生成树上),将这条边与环上除了这条边权值最大的边替换,就形成了新的生成树,在不断尝试新边的过程中维护一个最小的生成数的边权值和即是次小生成树的边权值和。

可以发现生成的环形成的路径即是两个端点与它们的LCA(最近公共祖先)的路径,所以可以用求LCA的办法顺便记录路径中边权的最大值。

 

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <queue>
  6 typedef long long ll;
  7 using namespace std;
  8 
  9 const int N=1e2+5;
 10 
 11 struct edge {
 12     int id;
 13     int from;
 14     int to;
 15     int val;
 16 }E[N<<2];
 17 
 18 struct cmp {
 19     bool operator()(edge a,edge b) {
 20         return a.val>b.val;
 21     }
 22 };
 23 
 24 int fir[N],nex[N<<2],cnt;
 25 int pre[N],dis[N],dep[N];
 26 bool vis[N],used[N<<1];
 27 int T=0,t,n,m,cost;
 28 
 29 void init() {
 30     memset(fir,-1,sizeof(fir));
 31     cost=cnt=0;
 32 }
 33 
 34 void connect(int from,int to,int val,int id) {
 35     E[cnt]=(edge){id,from,to,val};
 36     nex[cnt]=fir[from];
 37     fir[from]=cnt++;
 38     E[cnt]=(edge){id,to,from,val};
 39     nex[cnt]=fir[to];
 40     fir[to]=cnt++;
 41 }
 42 
 43 bool prim() {
 44     int node=0;记录生成树上的点的数量。
 45     memset(vis,false,sizeof(vis));
 46     memset(used,false,sizeof(used));
 47     priority_queue <edge,vector <edge>,cmp> Q;
 48     Q.push((edge){-1,0,1,0});
 49     dep[0]=0;
 50     while(!Q.empty()) {
 51         edge q=Q.top();
 52         Q.pop();
 53         if(vis[q.to]) continue;
 54         vis[q.to]=true;
 55         cost+=q.val; node++;
 56         pre[q.to]=q.from;
 57         dis[q.to]=q.val;
 58         dep[q.to]=dep[q.from]+1;//在求最小生成树的过程中顺便记录生成树上的点的深度以及父节点、与父节点连接的边的权值。
 59         used[q.id]=true;//记录哪些边在最小生成树上,到时在求次小生成树的过程中跳过这些边。
 60         for(int i=fir[q.to];i!=-1;i=nex[i]) {
 61             int to=E[i].to;
 62             if(!vis[to]) Q.push(E[i]);
 63         }
 64     }
 65     if(node<n) return false;生成树上的点少于n,说明不是连通图,无法形成最小生成树。
 66     return true;
 67 }
 68 
 69 int lca(int x,int y) {
 70     int MAX=0;
 71     if(dep[x]>dep[y]) swap(x,y);
 72     while(dep[y]>dep[x]) {
 73         MAX=max(MAX,dis[y]);
 74         y=pre[y];
 75     }
 76     while(x!=y) {
 77         MAX=max(MAX,dis[y]);
 78         y=pre[y];
 79         MAX=max(MAX,dis[x]);
 80         x=pre[x];
 81     }
 82     return MAX;
 83 }
 84 
 85 void solve() {
 86     bool flag=false;
 87     int second=2e9;
 88     for(int i=0;i<cnt;i+=2) {
 89         if(used[E[i].id]) continue;
 90         flag=true;
 91         second=min(second,cost+E[i].val-lca(E[i].from,E[i].to));
 92     }
 93     if(flag) printf("Case #%d : %d\n",++T,second);//若除了最小生成树上的边以外没有剩下的边,那么没有次小生成树。
 94     else printf("Case #%d : No second way\n",++T);
 95 }
 96 
 97 int main() {
 98     scanf("%d",&t);
 99     while(t--) {
100         scanf("%d%d",&n,&m);
101         init();
102         for(int i=1;i<=m;i++) {
103             int x,y,z;
104             scanf("%d%d%d",&x,&y,&z);
105             connect(x,y,z,i);
106         }
107         if(!prim()) {
108             printf("Case #%d : No way\n",++T); continue;
109         }
110         solve();
111     }
112     return 0;
113 }

 

标签:int,MAX,There,生成,dep,Second,10462,权值,include
来源: https://www.cnblogs.com/liaxiaoquan/p/12382612.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有