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; }