HDU6073-拓扑排序&搜索-Matching In Multiplication

来源:互联网 发布:mac 解压缩rar 编辑:程序博客网 时间:2024/06/05 11:45

http://acm.hdu.edu.cn/showproblem.php?pid=6073
给定一个二分图,左侧每个点都有两条边
求你他所有完美匹配 中各边之积的和。
1 先找右边只有一个边连接的,这种点肯定只有一种,并且这种关系会影响下一个,所以我们用topsort来弄,剩下的都是环了。
而对于环,若想完成完全匹配(顶点完全覆盖),则需要间隔的取边(画图发现qwq)
计算的过程是根据乘法原理qwq
错了20多次,因为在dfs的过程中的取余的过程中错了55 一直tle
因为点比较多,用邻接表也超时了qwq

#include <bits/stdc++.h>/* 1 topsort 判定度数为1的情况。   2 然后k环,k个集合。   每一个求多重集*/using namespace std;typedef long long ll;const long long mod=998244353;const int maxn=3e5+100;struct Node{      int from;      int to;      ll  cost;      int next;      int bh;//给每个边标号,因为我发现记录点无法完成。      Node(){};      Node(int _a,int _b,int _c){to=_a;cost=_b;bh=_c;};};int len;Node node[maxn*5];int head[maxn*2];void add(int a,int b,int c,int d){     node[len].from=a;     node[len].to=b;     node[len].cost=c;     node[len].bh=d;     node[len].next=head[a];     head[a]=len++;}ll cc[2];bool vis[maxn*4];bool vis2[maxn*2];int du[maxn*2];void dfs(int pre,int use){   vis2[pre]=true;     for(int i=head[pre];i!=-1;i=node[i].next){         int s=node[i].to;         int sss=node[i].bh;         if(vis[sss]) continue;         cc[use]=(cc[use]*node[i].cost)%mod;//         // 错误的  方法是 先计算cc 在取模,这样在取模前可能已经超时了         //cout<<use<<"!!"<<cc[use]<<endl;         while(cc[use]>mod)               cc[use]-=mod;         if(!vis[sss]){           vis[sss]=true;            vis[sss^1]=true;           dfs(s,1-use);           }     }}int main(){    //freopen("f:\\ttt\\data.txt","r",stdin);//freopen("f:\\ttt\\out2.txt","w",stdout);     int m;    int t;    int a;    ll b;    scanf("%d",&t);    while(t--){         scanf("%d",&m);         int cnt=0;         memset(head,-1,sizeof(head));         len=0;         memset(du,0,sizeof(du));         memset(vis,false,sizeof(vis));         memset(vis2,false,sizeof(vis2));         for(int i=1;i<=m;i++){             scanf("%d%lld",&a,&b);             //G[i].push_back(Node(a+m,b,cnt++));             add(i,a+m,b,cnt++);             add(a+m,i,b,cnt++);             //G[a+m].push_back(Node(i,b,cnt++));             du[i]++,du[a+m]++;             scanf("%d%lld",&a,&b);             //G[i].push_back(Node(a+m,b,cnt++));             //G[a+m].push_back(Node(i,b,cnt++));              add(i,a+m,b,cnt++);             add(a+m,i,b,cnt++);             du[i]++,du[a+m]++;         }         //cout<<"??????"<<endl;         queue<int>q;         for(int i=1;i<=m*2;i++){            if(du[i]==1){                q.push(i);                vis2[i]=true;                }         }         ll ans=1;         while(!q.empty()){               int u=q.front();               q.pop();               vis2[u]=true;               for(int i=head[u];i!=-1;i=node[i].next){                   int v=node[i].to;                   int bc=node[i].bh;                   if(vis[bc]) continue;                   if(vis2[v]) continue;                   while(node[i].cost>mod) node[i].cost-=mod;                   ans=(ans*node[i].cost)%mod;                   while(ans>mod)                         ans-=mod;//取模                   vis[bc]=true;                   vis[bc^1]=true;                   vis2[v]=true;                   for(int j=head[v];j!=-1;j=node[j].next){                       int vv=node[j].to;                       int bbh=node[j].bh;                       du[vv]--;                       vis[bbh]=true;                       vis[bbh^1]=true;                       if(du[vv]==1){                        q.push(vv);                        vis2[vv]=true;                       }                     }               }         }         //cout<<ans<<endl;         int sum=0;         for(int i=1;i<=2*m;i++){            cc[0]=1;cc[1]=1;            if(!vis2[i]){               dfs(i,0);            //if(cc[0]+cc[1]!=0)            ans=(ans*(cc[0]+cc[1])%mod)%mod;            while(ans>mod)                  ans-=mod;            }            //cout<<"过程"<<cc[0]<<" "<<cc[1]<<endl;            //cout<<"过程中的ans:"<<ans<<endl;         }         printf("%lld\n",ans);    }    return 0;}
阅读全文
0 0