一开始是用二分图匹配(网络流)+二分做的,后来发现直接用匈牙利更简单
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<vector> #include<queue> #define pii pair<int,int> #define X first #define Y second #define INF 0x7f7f7f7f #define MAXN 1000+10 using namespace std; struct Edge{ int from,to,cap,flow; Edge(int u=0,int v=0,int c=0,int f=0){ from=u,to=v,cap=c,flow=f; } }; struct Dinic{ int n,m,s,t; vector<Edge> edges; vector<int> G[MAXN<<1]; int d[MAXN<<1]; int b[MAXN<<1]; int cur[MAXN<<1]; void init(int n,int s,int t){ this->n=n; this->s=s,this->t=t; edges.clear(); for(int i=0;i<=n;i++){ G[i].clear(); } } void AddEdge(int x,int y,int cap){ edges.push_back(Edge(x,y,cap,0)); edges.push_back(Edge(y,x,0,0)); m=edges.size(); G[x].push_back(m-2); G[y].push_back(m-1); } bool BFS(){ memset(b,0,sizeof(b)); queue<int> q; d[s]=1; q.push(s); b[s]=1; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<G[x].size();i++){ Edge &e=edges[G[x][i]]; if(e.cap>e.flow&&!b[e.to]){ q.push(e.to); b[e.to]=1; d[e.to]=d[x]+1; } } } return b[t]; } int dfs(int x,int a){ if(x==t||!a)return a; int flow=0,f; for(int &i=cur[x];i<G[x].size();i++){ Edge &e=edges[G[x][i]]; if(d[e.to]==d[x]+1&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){ edges[G[x][i]].flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(!a){ break; } } } return flow; } int Maxflow(){ int flow=0; while(BFS()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,INF); } return flow; } }D; int n,m; pii a[MAXN]; int s[MAXN]; void print(int x){ for(int i=0;i<D.edges.size();i++){ Edge &e=D.edges[i]; if(e.flow>=1&&n+1<=e.to&&e.to<=n+x){ s[e.to-n]=e.from; } } for(int i=1;i<=x;i++){ printf("%d ",s[i]-1); } } void init(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&a[i].X,&a[i].Y); a[i].X++,a[i].Y++; } } int check(int x){ D.init(n+x+2,0,n+x+1); for(int i=1;i<=n;i++){ D.AddEdge(0,i,1); } for(int i=1;i<=x;i++){ D.AddEdge(a[i].X,n+i,1); D.AddEdge(a[i].Y,n+i,1); D.AddEdge(n+i,n+x+1,1); } int ans=D.Maxflow(); return (ans==x); } void solve(){ int L=0,R=m; while(R-L>1){ int mid=(L+R)/2; if(check(mid)){ L=mid; } else{ R=mid; } } if(check(R)){ printf("%d ",R); print(R); } else if(check(L)){ printf("%d ",L); print(L); } } int main() { //freopen("data.in","r",stdin); init(); solve(); return 0; }
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<vector> #include<queue> #define pii pair<int,int> #define X first #define Y second #define INF 0x7f7f7f7f #define MAXN 1000+10 using namespace std; int n,m; int girl[MAXN],boy[MAXN]; int used[MAXN]; int a[MAXN][2]; bool find(int x){ for(int i=0;i<=1;i++){ int y=a[x][i]; if(!used[y]){ used[y]=1; if(!girl[y]||find(girl[y])){ girl[y]=x; boy[x]=y; return 1; } } } return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); x++,y++; a[i][0]=x,a[i][1]=y; } int ans=0; for(int i=1;i<=m;i++){ memset(used,0,sizeof(used)); if(find(i)) ans++; else break; } printf("%d ",ans); for(int i=1;i<=ans;i++){ printf("%d ",boy[i]-1); } return 0; }