Codeforces-557D Vitaly and Cycle(二分图染色)
2017-07-31 17:55
435 查看
题意:
N个节点,M条边的无向图(不一定连通),问你最少添加多少条边才能找到一个奇圈,并求出相应可行的方法数。
思路:
1. 会发现t只有0,1,2,3四种答案。
2. 当原图构不成二分图时即存在奇数环时直接输出0 1即可;
3. 而当图中不存在边时,则只需要3条边,然后通过画图得到求其种类的方法,感觉这儿挺难找。每次必选一个绿点,然后确定一个点连成直线,再去确定第三个点,然后从图中去掉当前的必选的点,然后再这样进行找即可。如下图:
4. 当图
4000
中存在长度大于等于2的连通块时,再通过染色进行寻找,由于是要求构成奇数环,所以同种颜色的点之间连线就可构成一个奇数环。当所有连通块的长度都是2时,更容易做,即通过这唯一一条边去连其它点即可。
代码:
继续加油~
N个节点,M条边的无向图(不一定连通),问你最少添加多少条边才能找到一个奇圈,并求出相应可行的方法数。
思路:
1. 会发现t只有0,1,2,3四种答案。
2. 当原图构不成二分图时即存在奇数环时直接输出0 1即可;
3. 而当图中不存在边时,则只需要3条边,然后通过画图得到求其种类的方法,感觉这儿挺难找。每次必选一个绿点,然后确定一个点连成直线,再去确定第三个点,然后从图中去掉当前的必选的点,然后再这样进行找即可。如下图:
4. 当图
4000
中存在长度大于等于2的连通块时,再通过染色进行寻找,由于是要求构成奇数环,所以同种颜色的点之间连线就可构成一个奇数环。当所有连通块的长度都是2时,更容易做,即通过这唯一一条边去连其它点即可。
代码:
#include <algorithm> #include <string.h> #include <cstdio> #define LL long long using namespace std; const int maxn = 1e5+5; const int maxm = maxn*2; struct node { int v, next; } edge[maxm]; int no, head[maxn]; int n, m; int col[maxn]; //每个点的颜色 LL key[2], flag; //key记录A部和B部的点数,flag用于判断是否构成二分图 inline void init() { no = 0; flag = 0; memset(head, -1, sizeof head); memset(col, -1, sizeof col); } inline void add(int u, int v) { edge[no].v = v; edge[no].next = head[u]; head[u] = no++; } void dfs(int cur, int father, int color) { col[cur] = color; ++key[color]; for(int k = head[cur]; k != -1; k = edge[k].next) { if(flag) return; if(edge[k].v == father) continue; if(col[edge[k].v] == color) //连边的两个点属于同一部 { flag = 1; return; } if(col[edge[k].v] != -1) continue; dfs(edge[k].v, cur, color^1); } } int main() { int u, v, t; LL w; scanf("%d %d", &n, &m); init(); for(int i = 1; i <= m; ++i) { scanf("%d %d", &u, &v); add(u, v); add(v, u); } if(m == 0) { LL ans = 0, t; for(int i = n-2, j = 1; i >= 1; --i, ++j) ans += (LL)i*j; printf("3 %lld\n", ans); return 0; } t = 2, w = 0; for(int i = 1; i <= n; ++i) { if(col[i] != -1) continue; key[0] = key[1] = 0; dfs(i, -1, 1); if(flag) { puts("0 1"); return 0; } if(key[0]+key[1] < 2) continue; //单个点的连通块直接忽略 if(key[0]+key[1] == 2) { if(t == 1) continue; w += n-2; } if(key[0]+key[1] > 2) { if(t == 2) t = 1, w = 0; if(key[0]) w += (key[0]-1)*key[0]/2; if(key[1]) w += (key[1]-1)*key[1]/2; } } printf("%d %lld\n", t, w); return 0; }
继续加油~
相关文章推荐
- CodeForces - 862B (二分图染色)
- Codeforces 557D - Vitaly and Cycle [二分图染色]【图论】
- CodeForces 624C Graph and String(二分图染色)
- Codeforces 664D Graph Coloring 二分图染色
- Codeforces 557D Vitaly and Cycle 【染色判二分图 + 组合数学】
- codeforces 624C 二分图染色
- Codeforces 624C:Graph and String 二分图染色
- Codeforces 557D Vitaly and Cycle【二分图染色+思维】好题~
- 【CodeForces - 687A NP-Hard Problem】 二分图染色
- CodeForces 687A - NP-Hard Problem(二分图染色)
- Codeforces-687A NP-Hard Problem(二分图染色)
- codeforces 557D Vitaly and Cyclef(二分图染色)
- [Codeforces 27D] Ring Road 2 (二分图染色)
- Codeforces 862 B Mahmoud and Ehab and the bipartiteness(二分图染色)
- CodeForces 624C【二分图染色】
- 「美团 CodeM 初赛 Round A」二分图染色 容斥原理
- codeforces 557 D. Vitaly and Cycle 组合数学 + 判断二分图
- 图论总结 Dijkstra Tarjan 最小生成树 二分图 最短路 强连通分量 双连通分量 Bellman-Ford SPFA 二分图染色 Kruskal Prim 网络流 二分图匹配 Dinic
- 洛谷P1330 封锁阳光大学(二分图染色)
- [HDU 5313] Bipartite Graph 二分图染色+分组背包