HDU_6073 Matching In Multiplication 【二分图&&拓扑排序&&DFS】
2017-08-10 08:18
375 查看
题目链接
题目描述
如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图。准确地说:把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U、V中的顶点。如果存在这样的划分,则此图为一个二分图。二分图的一个等价定义是:不含有「含奇数条边的环」的图完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。但是小Q错误的理解了二分图的定义,以为二分图的两个顶点集u和v的大小相等,u中的每个顶点p都可以引出两条边,它定义了一个二分图的权重就是每个完美匹配的权重相加,每个完美匹配的权重是这个完美匹配中所有边的乘积。解题思路
首先如果一个点的度数为1,那么它的匹配方案是固定的,继而我们可以去掉这一对点。通过拓扑我们可以不断去掉所有度数为1的点。那么剩下的图中左右各有m个点,每个点度数都不小于2,且左边每个点度数都是2,而右侧总度数是2m,因此右侧只能是每个点度数都是2。这说明这个图每个连通块是个环,在环上间隔着取即可,一共两种方案。代码部分
#include<bits/stdc++.h> using namespace std; const int mod = 998244353; const int N = 300000 + 10; struct Edge { int nxt, to, w; bool mrk; } e[N*4];///构造领接链表的边结点 int T, n, head[N*2], cnt, deg[N*2], used[N*2]; ///T表示测试数据的组数,n表示节点个数,head表示头结点,deg记录每个结点的度,used表示这个节点是否被匹配过 long long part[2];///part表示最后剩的那两部分 void addedge(int u, int v, int w) {///构造领接链表 e[++cnt].nxt = head[u]; e[cnt].to = v; e[cnt].w = w; e[cnt].mrk = 0; head[u] = cnt; } void dfs(int cur, int idx) { ///因为要隔着取所以我们可以用part[0]表示一种情况,part[1]表示另一种情况,然后每次改变idx的值 used[cur] = 1;///表示这个顶点已经找过了,不能再找,所以要标记一下 for(int i=head[cur];i;i=e[i].nxt) { if(e[i].mrk) continue;///如果这个顶点已经被用了,就跳过 e[i].mrk = e[i^1].mrk = 1;///没有则标记,并把它对应的那个点也标记了 (part[idx] *= e[i].w) %= mod;///每个完美匹配的累乘 dfs(e[i].to, 1-idx);///递归寻找另一个完美匹配边 } } int main() { scanf("%d", &T); while(T-- && scanf("%d", &n)!=EOF) { memset(head, 0, sizeof(head)); memset(deg, 0, sizeof(deg)); memset(used, 0, sizeof(used)); cnt = 1; for(int u=1, v, w;u<=n;u++) for(int i=1;i<=2;i++) { scanf("%d %d", &v, &w); addedge(u, v+n, w); addedge(v+n, u, w); deg[u]++, deg[v+n]++; } long long ans = 1; queue<int> que; for(int v=n+1;v<=n+n;v++) if(deg[v] == 1) que.push(v); while(!que.empty())///对所有度为1的点进行拓扑排序,并去掉度为1节点 { int v = que.front(); que.pop(); used[v] = 1;///标记度为1的节点 for(int i=head[v];i;i=e[i].nxt) { if(e[i].mrk) continue; e[i].mrk = e[i^1].mrk = 1; used[ e[i].to ] = 1;///因为该节点与度为1的节点相连,所以也要去掉 (ans *= e[i].w) %= mod; for(int j=head[ e[i].to ];j;j=e[j].nxt)///将于这个点相连的所有边去掉,判断去掉便后,剩余节点的度是否为1,如果为1也要加入队列中 { e[j].mrk = e[j^1].mrk = 1; deg[e[j].to]--; if(deg[ e[j].to ] == 1) que.push(e[j].to); } } } //cout<<"ans: "<<ans<<endl; for(int u=1;u<=n;u++) { if(used[u]) continue; part[0] = part[1] = 1; dfs(u, 0);///调用dfs计算剩余的完美匹配 (ans *= (part[0]+part[1]) % mod) %= mod; } printf("%lld\n", ans); } }
相关文章推荐
- HDU-6073 Matching In Multiplication(拓扑+dfs)
- hdu 6073 Matching In Multiplication [dfs]
- 2017多校第4场 HDU 6073 Matching In Multiplication 拓扑排序,思维,DFS
- HDU 6073 Matching In Multiplication (拓扑+DFS, 2017 Multi-Univ Training Contest 4)
- hdu 6073 Matching In Multiplication(拓扑排序+欧拉回路)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication(拓扑+思维)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication(拓扑排序+思维)
- 【多校训练】hdu 6073 Matching In Multiplication. 拓扑+dfs
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication (拓扑排序+搜索 求二分图所有完美匹配价值和)
- HDU 6073 Matching In Multiplication
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- hdu 6073 Matching In Multiplication (二分图与拓补排序)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- Matching In Multiplication(HDU 6073)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication(拓扑排序)