其实吧,思路挺简单的,只不过昨天刚学,还有一些东西不太了解,然后就23333333.。。
吃晚饭回来就A了,我是有多傻啊,这么题都A不掉,不能忍啊。。。
我们可以先求出哪些边是可能存在于最大匹配中的,然后剩下的边就是绝对不可能在最大匹配中了
求哪些边可能存在于最大匹配中,超简单,只需要强制将那条边上的两个点匹配(即删除),然后求最大匹配,如果是tot-1,那么这条边就可以存在于最大匹配中。
ps:比赛的时候直接match[u]=v match[v]=u了,队友其实给我提供过正确的思路,只不过我太傻x,说多了都是泪。。。
/* ********************************************** Author : wuyiqi Created Time: 2013-8-20 15:55:42 File Name : 1002.cpp *********************************************** */ #include <iostream> #include <stdio.h> #include <string.h> #include <cmath> #include <algorithm> #include <queue> #include <vector> using namespace std; //#define MAXE 300*300*2 #define MAXN 300 #define SET(a,b) memset(a,b,sizeof(a)) deque<int> Q; //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点 bool g[MAXN][MAXN],inque[MAXN],inblossom[MAXN]; int match[MAXN],pre[MAXN],base[MAXN]; //找公共祖先 int findancestor(int u,int v) { bool inpath[MAXN]={false}; while(1) { u=base[u]; inpath[u]=true; if(match[u]==-1)break; u=pre[match[u]]; } while(1) { v=base[v]; if(inpath[v])return v; v=pre[match[v]]; } } //压缩花 void reset(int u,int anc) { while(u!=anc) { int v=match[u]; inblossom[base[u]]=1; inblossom[base[v]]=1; v=pre[v]; if(base[v]!=anc)pre[v]=match[u]; u=v; } } void contract(int u,int v,int n) { int anc=findancestor(u,v); SET(inblossom,0); reset(u,anc);reset(v,anc); if(base[u]!=anc)pre[u]=v; if(base[v]!=anc)pre[v]=u; for(int i=1;i<=n;i++) if(inblossom[base[i]]) { base[i]=anc; if(!inque[i]) { Q.push_back(i); inque[i]=1; } } } bool dfs(int S,int n) { for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i; Q.clear();Q.push_back(S);inque[S]=1; while(!Q.empty()) { int u=Q.front();Q.pop_front(); for(int v=1;v<=n;v++) { if(g[u][v]&&base[v]!=base[u]&&match[u]!=v) { if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n); else if(pre[v]==-1) { pre[v]=u; if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1; else { u=v; while(u!=-1) { v=pre[u]; int w=match[v]; match[u]=v; match[v]=u; u=w; } return true; } } } } } return false; } int solve(int n) { SET(match,-1); int ans=0; for(int i=1;i<=n;i++) if(match[i]==-1&&dfs(i,n)) ans++; return ans; } bool vis[200]; int a[200],b[200]; bool mp[200][200]; int main() { int n , m; while(scanf("%d%d",&n,&m) != EOF) { memset(g,false,sizeof(g)); memset(vis,false,sizeof(vis)); memset(mp,false,sizeof(mp)); for(int i = 1; i <= m; i++) { scanf("%d%d",&a[i],&b[i]); g[a[i]][b[i]] = g[b[i]][a[i]] = true; mp[a[i]][b[i]] = mp[b[i]][a[i]] = true; } int ans = solve(n); for(int i = 1; i <= m; i++) { int x = a[i] , y = b[i]; memset(g,false,sizeof(g)); for(int j = 1; j <= m; j++) if(i!=j){ if(a[j] == y && b[j] == x) continue; int aa = a[j] , bb = b[j]; if(aa==x || aa==y || bb==x || bb==y) continue; g[aa][bb] = g[bb][aa] = true; } int tmp = solve(n); if(tmp == ans - 1) { vis[i] = true; } } vector<int> ret; for(int i = 1; i <= m; i++) if(!vis[i]) { ret.push_back(i); } printf("%d ",ret.size()); if(ret.size()>0) { printf("%d",ret[0]); for(int i = 1; i < ret.size(); i++) { printf(" %d",ret[i]); } } puts(""); } return 0; }