您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: