[2016-03-05][UVALive][4059][Inspector's Dilemma]
[2016-03-05][UVALive][4059][Inspector's Dilemma]
- 时间:2016-03-05 19:37:31 星期六
- 题目编号:UVALive 4059
- 题目大意:一个国家有n个城市,每2个城市都有道路相连,已知从一个城市到另一个城市的时间为T,某检查工人需要检查其中E段路,问最少需要花费多少时间
- 输入:
- 若干组数据,以0 0 0结束
- 每组数据:
- V,E,T城市数目,需要检查的路的数目,T时间
- 接下来E行,每行2个数字,表示a b城市的道路需要检查
- 输出:每组数据Case cntcase: ans\n
- 分析:给定一个完全图和图上的一些边,求走完给定的边至少要走完全图上的多少条边。
- 方法:
- 假设有k个联通块,那么每个联通块肯定可以分开计算,
- 然后从一个联通块到另一个联通块需要走k-1条边,
- 对于每个联通块,如果存在欧拉回路和欧拉路径,那么一定可以一次走完
- 如果不存在,那么就看奇度点的个数,如果个数大于2,那么就要多走 (cnt - 2)/2条边
- 所以最后答案就是 M + sum{ (cnt-2)/2 } + k - 1(M为有边的联通块的数目)
- 解决方法:直接计算每个联通块的边数,加上有边联通块数目,加上每个联通块奇度点的情况对应的数字
- 解题过程遇到问题:
- 边数为0的情况,应该输出0
- 有的联通块没有边的情况(单独一个点),那么这个联通块是不需要计算的
//方法1:并查集 #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x)) #define FORD(x,y,z) for(int (x)=(y);(x)>=(z);--(x)) #define FOR2(x,y,z) for((x)=(y);(x)<(z);++(x)) #define FORD2(x,y,z) for((x)=(y);(x)>=(z);--(x)) const int maxv = 1000 + 100; vector<int> v[maxv]; int fa[maxv],cntodd[maxv];//cntodd 保存每个联通块奇度顶点的个数 void ini(int n){ FOR(i,1,n + 1){ fa[i] = i; v[i].clear(); cntodd[i] = 0; } } int fnd(int x){ return x == fa[x]?x:fa[x] = fnd(fa[x]); } void uni(int x,int y){ fa[fnd(x)] = fnd(y); } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int V,E,T,cntcase = 0; while(~scanf("%d%d%d",&V,&E,&T) && (V||E||T)){ int u1,v1; ini(V); FOR(i,0,E){ scanf("%d%d",&u1,&v1); uni(u1,v1); v[u1].push_back(v1); v[v1].push_back(u1); } //计算有边联通块的数目 和 每个联通块奇度顶点的个数 int cntfa = 0,res = 0; FOR(i,1,V + 1){ if(fa[i] == i && v[i].size()) ++cntfa; if( v[i].size() & 1) ++cntodd[fnd(i)]; } //判断每个联通块奇度顶点个数 FOR(i,1,V + 1) if(fa[i] == i && cntodd[i] > 2) res += (cntodd[i] - 2)/2; //如果有效联通块的数目为0,即没有边,那么就不需要减1 res += E + (cntfa>1? cntfa - 1:0); printf("Case %d: %d\n",++cntcase,res*T); } return 0; } |
//方法2:dfs #include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; typedef long long LL; #define CLR(x,y) memset((x),(y),sizeof((x))) #define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x)) #define FORD(x,y,z) for(int (x)=(y);(x)>=(z);--(x)) #define FOR2(x,y,z) for((x)=(y);(x)<(z);++(x)) #define FORD2(x,y,z) for((x)=(y);(x)>=(z);--(x)) const int maxn = 1000 + 10; const int maxedge = maxn * maxn; int head[maxn]; int nextt[maxedge]; int endd[maxedge]; void addedge(int from,int to){ static int q = 2; endd[q] = to; nextt[q] = head[from]; head[from] = q++; } int d[maxn],vis[maxn]; void dfs(int cur,int & cntodd){ vis[cur] = 1; if(d[cur] & 1) ++cntodd; for(int q = head[cur];~q;q = nextt[q]){ int v = endd[q]; if(!vis[v]) dfs(v,cntodd); } } //初始化 void ini(){ memset(head,-1,sizeof(head)); memset(nextt,-1,sizeof(nextt)); memset(endd,-1,sizeof(endd)); CLR(d,0);CLR(vis,0); } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int V,E,T,cntcase = 0; while(~scanf("%d%d%d",&V,&E,&T) && (V||E||T)){ int u1,v1; ini(); FOR(i,0,E){ scanf("%d%d",&u1,&v1); addedge(u1,v1); addedge(v1,u1); ++d[v1];++d[u1]; } int res = E; FOR(i,1,V+1){ //计算每个有边联通块奇度点的个数. if(!vis[i] && head[i] != -1){ ++res; int cntodd = 0; dfs(i,cntodd); if(cntodd > 2) res += (cntodd - 2)/2; } } if(res) --res; printf("Case %d: %d\n",++cntcase,res*T); } return 0; } |
浙公网安备 33010602011771号