HDU 6073 Matching In Multiplication(强连通+拓扑)

来源:互联网 发布:win32编程视频教程 编辑:程序博客网 时间:2024/05/17 03:17

思路:

先找右边节点入度为1的点,设为b,所以这个点连的边一定做出了贡献。然后找左边连这个点b的点a。
将a所连的点的入度都减减,如果出现入度为1的,那么接着从这个点搜。
直到没有这样的点。
所以剩下的点都在环里。
跑一边tarjan,然后在各自的联通分量内跑一圈,注意:环的贡献由两部分组成,因为是选一条边不选一条边,所以反过来就又有一种。

#include<stdio.h>#include<string.h>#include<math.h>#include <queue>#include<algorithm>#define eps 1e-8typedef 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[now];~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;}
阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 眼镜腿中间断了怎么办 塑料眼镜腿断了怎么办 眼镜上的螺丝拧不紧怎么办 眼镜的把坏了怎么办 把眼镜坐坏了怎么办 梦见眼镜腿掉了怎么办 眼镜的腿掉了怎么办 眼镜腿的螺丝掉了怎么办 爱大爱眼镜掉腿了怎么办 合金眼镜腿断了怎么办 手关节复位h疼痛怎么办 我叫mt红色卡牌怎么办 星盟冲突qq登录怎么办 汽车雷达下雨一直响怎么办 火山小视频封火力怎么办 电脑被当成矿机怎么办 哥华有线机顶盒反应慢怎么办 电脑绣花机编码器坏了怎么办? 伺服电机开起没有力怎么办 西门子冰箱排水孔堵塞怎么办 数控车床西门子系统卡顿怎么办 手机系统不支持多屏互动怎么办 伺服驱动器系统错误报警怎么办 防雷接地电阻不符合规范怎么办 微信支付风控了怎么办 伺服电机没有配原点开关怎么办 电脑自带游戏打不开怎么办 战地1更新很慢怎么办 客户端提示初始化控件失败怎么办 刺客信条兄弟会存档损坏怎么办 百度不小心点赞怎么办 c盘空间不够了怎么办 百度云打开压缩文件失败怎么办 电脑只有一个c盘怎么办 u盘文件删不了怎么办 在电脑上照片打不开乱码怎么办 win7电脑登录密码忘记了怎么办 三洋电视应用商店打不开怎么办 中兴手机应用商店打不开怎么办 绝地求生与服务器失去连接怎么办 战地4载入不进去怎么办