HDU 6073 Matching In Multiplication(强连通+拓扑)
2017-08-03 19:38
489 查看
思路:
先找右边节点入度为1的点,设为b,所以这个点连的边一定做出了贡献。然后找左边连这个点b的点a。将a所连的点的入度都减减,如果出现入度为1的,那么接着从这个点搜。
直到没有这样的点。
所以剩下的点都在环里。
跑一边tarjan,然后在各自的联通分量内跑一圈,注意:环的贡献由两部分组成,因为是选一条边不选一条边,所以反过来就又有一种。
#include<stdio.h> #include<string.h> #include<math.h> #include <queue> #include<algorithm> #define eps 1e-8 typedef long long int lli; using namespace std; const int maxn = 650000; const int mod = 998244353; struct edge{ int to,v,next; }ed[maxn*10]; int head[maxn],cnte; void ae(int x,int y,int v){ ed[++cnte].to = y; ed[cnte].v = v; ed[cnte].next = head[x]; head[x] = cnte; } lli dfn[maxn],low[maxn],stak[maxn],belong[maxn],cntc,cnts,index; bool vis[maxn];int vc[maxn]; void dfs(lli u,lli f){ dfn[u] = low[u] = ++index; stak[cnts++] = u; vis[u] = 1; for(lli i = head[u];~i;i=ed[i].next){ lli v = ed[i].to; if(v == f) continue; if(!dfn[v]){ dfs(v,u); low[u] = min(low[u],low[v]); } else if(vis[v]) low[u] = min(low[u],dfn[v]); } if(dfn[u] == low[u]){ cntc++;lli v;int cnt =0; do{ cnt++; v = stak[--cnts]; vis[v] = 0; belong[v] = cntc; }while(v!=u); if(cnt == 1) vc[u] = 2; } } int n; void tarjan(){ for(int i = 1;i <= n;i++){ if(!dfn[i]) dfs(i,-1); } } bool v[maxn]; void df(int p,lli &ta1,lli &ta2,int fl){ for(int i = head[p];~i;i=ed[i].next){ int to = ed[i].to; if(v[to]==0 && belong[to]==belong[p]){ v[to] = 1; if(fl == 1) ta1 = ta1*(lli)ed[i].v%mod; else ta2 = ta2*(lli)ed[i].v%mod; df(to,ta1,ta2,-fl); } } } int in[maxn]; void ini(){ memset(head,-1,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(vc,0,sizeof(vc)); memset(v,0,sizeof(v)); memset(in,0,sizeof(in)); cnte = cntc = cnts = index = 0; } int main(){ int t; scanf("%d",&t); while(t--){ ini(); scanf("%d",&n); int t1,t2,t3,t4; for(int i = 1;i <= n;i++){ scanf("%d%d%d%d",&t1,&t2,&t3,&t4); ae(i,n+t1,t2);ae(t1+n,i,t2); ae(i,n+t3,t4);ae(t3+n,i,t4); in[t1+n]++;in[t3+n]++; } tarjan(); lli ans = 1,tans1,tans2;tans1 = 1; queue<int> q;int now; for(int i = n+1;i <= n+n;i++){ if(in[i] == 1){ q.push(i); } } while(!q.empty()){ now = q.front();q.pop(); int to,va; for(int i = head[n 4000 ow];~i;i=ed[i].next){ int des = ed[i].to; if(!v[des]){ to = des,va = ed[i].v;break; } } ans = ans*(lli)va%mod;v[to] = 1; for(int i = head[to];~i;i=ed[i].next){ int v2 = ed[i].to; in[v2]--; if(in[v2]==1) q.push(v2); } } for(int i = 1;i <= n;i++){ if(!vc[i]&&!v[i]){ tans1 = tans2 = 1; vc[i] = 1; df(i,tans1,tans2,1); ans = ans*((tans1+tans2)%mod) % mod; } } printf("%lld\n",(ans%mod+mod)%mod); } return 0; }
相关文章推荐
- HDU 6073 Matching In Multiplication (拓扑+DFS, 2017 Multi-Univ Training Contest 4)
- HDU 6073 Matching In Multiplication(拓扑+思维)
- 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. 拓扑+dfs
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- 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(2017 Multi-University Training Contest - Team 4 )
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- 2017多校第4场 HDU 6073 Matching In Multiplication 拓扑排序,思维,DFS
- 2017多校四 1007题 hdu 6073 Matching In Multiplication 拓扑排序 + 找环
- hdu 6073 Matching In Multiplication(2017 Multi-University Training Contest - Team 4 )
- HDU 6073 Matching In Multiplication(拓扑排序)
- 2017多校四 1007题 hdu 6073 Matching In Multiplication 拓扑排序 + 找环
- Matching In Multiplication(HDU 6073)
- HDU 6073 Matching In Multiplication