HDU 6073 Matching In Multiplication(拓扑排序+思维)
2017-08-07 17:11
435 查看
http://acm.hdu.edu.cn/showproblem.php?pid=6073
题意:
有个二分图,左边和右边的顶点数相同,左边的顶点每个顶点度数为2。现在有个屌丝理解错了最佳完美匹配,它以为最佳完美匹配是边权的乘积了,现在要你计算所有这种最佳完美匹配的边权乘积和。保证至少存在一个完美匹配。
思路:
这道题目虽然打着二分图的幌子,但其实吧,根本就不是二分图,哎。
对于右边的点来说,如果它的度数为1,那么与它匹配的点肯定是确定的,所以我们先通过拓扑排序来计算出所有确定的匹配。去除这些点后,假设左边和右边各还剩下x个点,此时还有2x条边,此时右边顶点每个顶点的度数必为2。
此时其实就是连通图,对于左边的每一个顶点,它都有两种边可供选择,然而一旦确定了一条边之后,整个环就都确定下来了,所以对于一个环来说共有两种选择方法。
参考了大神的dfs方法,太强了!!!
题意:
有个二分图,左边和右边的顶点数相同,左边的顶点每个顶点度数为2。现在有个屌丝理解错了最佳完美匹配,它以为最佳完美匹配是边权的乘积了,现在要你计算所有这种最佳完美匹配的边权乘积和。保证至少存在一个完美匹配。
思路:
这道题目虽然打着二分图的幌子,但其实吧,根本就不是二分图,哎。
对于右边的点来说,如果它的度数为1,那么与它匹配的点肯定是确定的,所以我们先通过拓扑排序来计算出所有确定的匹配。去除这些点后,假设左边和右边各还剩下x个点,此时还有2x条边,此时右边顶点每个顶点的度数必为2。
此时其实就是连通图,对于左边的每一个顶点,它都有两种边可供选择,然而一旦确定了一条边之后,整个环就都确定下来了,所以对于一个环来说共有两种选择方法。
参考了大神的dfs方法,太强了!!!
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int INF = 0x3f3f3f3f; const int maxn=3e5+5; const int mod=998244353; int n; int tot, head[2*maxn]; int del[2*maxn], deg[maxn]; ll res[3]; struct node { int v, w, next; int mark; }e[4*maxn]; void addEdge(int u, int v, int w) { e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; e[tot].mark=0; head[u]=tot++; } void init() { tot=0; memset(head,-1,sizeof(head)); memset(deg,0,sizeof(deg)); memset(del,0,sizeof(del)); } void dfs(int u, int flag) { del[u]=1; for(int i=head[u];i!=-1;i=e[i].next) { if(e[i].mark) continue; int v=e[i].v; e[i].mark=e[i^1].mark=1; res[flag]=(res[flag]*e[i].w)%mod; dfs(v,flag^1); } } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(int i=1;i<=n;i++) { int v1,d1,v2,d2; scanf("%d%d%d%d",&v1,&d1,&v2,&d2); addEdge(i,v1+n,d1); addEdge(v1+n,i,d1); addEdge(i,v2+n,d2); addEdge(v2+n,i,d2); deg[v1]++; deg[v2]++; } ll ans=1; queue<int> Q; for(int i=1;i<=n;i++) if(deg[i]==1) Q.push(i+n); while(!Q.empty()) { int u=Q.front(); Q.pop(); del[u]=1; for(int i=head[u];i!=-1;i=e[i].next) //左边 { if(e[i].mark) continue; int v=e[i].v; del[v]=1; e[i].mark=e[i^1].mark=1; ans=(ans*e[i].w)%mod; for(int j=head[v];j!=-1;j=e[j].next) //右边 { if(e[j].mark) continue; int p=e[j].v; deg[p-n]--; e[j].mark=e[j^1].mark=1; if(deg[p-n]==1) Q.push(p); } } } for(int i=1;i<=n;i++) { if(!del[i]) { res[0]=res[1]=1; dfs(i,0); ans=(ans*((res[0]%mod+res[1]%mod)%mod))%mod; } } printf("%I64d\n",ans); } return 0; }
相关文章推荐
- HDU 6073 Multi-University Training Contest - Team 4 1007 :Matching In Multiplication:拓扑排序+思维
- HDU 6073 Matching In Multiplication 思维(拓扑)
- HDU 6073 Matching In Multiplication(拓扑+思维)
- 2017多校第4场 HDU 6073 Matching In Multiplication 拓扑排序,思维,DFS
- 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(拓扑排序)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- 2017多校四 1007题 hdu 6073 Matching In Multiplication 拓扑排序 + 找环
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- 2017多校四 1007题 hdu 6073 Matching In Multiplication 拓扑排序 + 找环
- hdu 6073 Matching In Multiplication [dfs]
- HDU-6073 Matching In Multiplication(拓扑+dfs)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication (拓扑+DFS, 2017 Multi-Univ Training Contest 4)
- 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(拓扑排序+欧拉回路)
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )