题目:
某个国家有V(V≤1000)个城市,每两个城市之间都有一条双向道路直接相连,长度为T(每条边的长度都是T)。你的任务是找一条最短的道路(起点和终点任意),
使得该道路经过E条指定的边。输出这条道路的长度。
思路:
看完题目给出的两组数据,知道是一个欧拉路径的题目,然后考虑用并查集来统计连通分量的个数,然后答案就是这个个数减一+给出的边数E……
这题细思极恐,如果一个连通分量里边有多个奇点,那么这样只统计连通分量个数的做法就不对了。
这是一个无向连通图,那么对于每一个连通分量我们可以把它变成一个欧拉路径。再把所有的欧拉路径合成一个。
在合并的时候,每两个奇点可以用一条边来连接,除去最终留下的两个奇点,这样(奇点总数-2)/2-1+给出的边数就是答案。
对于是环的连通分量,可以默认他的奇点的个数是2.
如果给出的图只有一个点,那么答案一定是0.
代码:
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define MAX 1000000009 #define FRE() freopen("in.txt","r",stdin) #define FRO() freopen("out.txt","w",stdout) using namespace std; typedef long long ll; const int maxn = 500010; vector<int> mp[maxn]; int V,T,E; int vis[maxn]; int DFS(int u){ if(vis[u]) return 0; //cout<<"GG: "<<u<<endl; vis[u] = 1; int cnt=0;//奇点的个数 if(mp[u].size()%2) cnt++; for(int i=0; i<mp[u].size(); i++){ cnt += DFS(mp[u][i]); } return cnt; } int main(){ //FRE(); int cs = 0; ios::sync_with_stdio(false); while(cin>>V>>E>>T && V){ for(int i=0; i<2*V; i++){ mp[i].clear(); } for(int i=0; i<E; i++){ int st,en; cin>>st>>en; mp[st].push_back(en); mp[en].push_back(st); } memset(vis,0,sizeof(vis)); int ans=0; for(int i=1; i<=V; i++){//统计图中一共有多少个奇点 if(!vis[i] && mp[i].size()){ ans += max(DFS(i),2); //cout<<ans<<endl; } } ans = max(0,(ans-2)/2)+E;//处理图中只有一个点的情况 cout<<"Case "<<++cs<<": "<<ans*T<<endl; } return 0; }