【HAOI2017】新型城市化
题面
https://www.luogu.org/problem/P3731
题解
二分图上求可能割边。
#include<queue> #include<stack> #include<vector> #include<cstdio> #include<utility> #include<cstring> #include<iostream> #include<algorithm> #define N 10050 #define M 150050 #define INF 1000000007 #define S 0 #define T (n+1) #define LL long long #define ri register int using namespace std; int n,m,u[M],v[M]; vector<int> to[N]; int col[N],dfn[N]; pair<int,int> ans[M]; inline int read() { int ret=0,f=0; char ch=getchar(); while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar(); return f?-ret:ret; } struct graph { vector<int> ed[N]; vector<int> w,to; int d[N],cur[N]; int bel[N],dfn[N],low[N],cc,cnt; bool ins[N]; stack<int> stk; void add_edge(int u,int v,int tw) { to.push_back(v); w.push_back(tw); ed[u].push_back(to.size()-1); to.push_back(u); w.push_back(0) ; ed[v].push_back(to.size()-1); } bool bfs() { queue<int> q; memset(d,0x3f,sizeof(d)); d[S]=0; q.push(S); while (!q.empty()) { int x=q.front(); q.pop(); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (d[x]+1<d[to[e]] && w[e]) { d[to[e]]=d[x]+1; q.push(to[e]); } } } return d[T]<INF; } int dfs(int x,int limit) { if (x==T || limit==0) return limit; int sum=0; for (ri &i=cur[x];i<ed[x].size();i++) { int e=ed[x][i]; if (w[e] && d[x]+1==d[to[e]]) { int f=dfs(to[e],min(limit,w[e])); if (!f) continue; sum+=f; limit-=f; w[e]-=f; w[1^e]+=f; if (!limit) return sum; } } return sum; } int dinic() { int ret=0; while (bfs()) { memset(cur,0,sizeof(cur)); ret+=dfs(S,INF); } return ret; } void tarjan(int x) { dfn[x]=low[x]=++cc; ins[x]=1; stk.push(x); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (!w[e]) continue; if (dfn[to[e]]) { if (ins[to[e]]) low[x]=min(low[x],dfn[to[e]]); } else { tarjan(to[e]); low[x]=min(low[x],low[to[e]]); } } if (dfn[x]==low[x]) { int t; ++cnt; do { t=stk.top(); stk.pop(); ins[t]=0; bel[t]=cnt; } while (t!=x); } } } G; void dfs(int x,int s) { dfn[x]=1; col[x]=s; for (ri i=0;i<to[x].size();i++) { int y=to[x][i]; if (!dfn[y]) dfs(y,s^1); } } int main(){ n=read(); m=read(); for (ri i=1;i<=m;i++) { u[i]=read(); v[i]=read(); to[u[i]].push_back(v[i]); to[v[i]].push_back(u[i]); } for (ri i=1;i<=n;i++) if (!dfn[i]) dfs(i,0); for (ri i=1;i<=m;i++) { if (col[u[i]]) G.add_edge(u[i],v[i],1); else G.add_edge(v[i],u[i],1); } for (ri i=1;i<=n;i++) if (col[i]) G.add_edge(S,i,1); else G.add_edge(i,T,1); G.dinic(); for (ri i=1;i<=n;i++) if (!G.dfn[i]) G.tarjan(i); int cc=0; for (ri i=0;i<G.w.size();i+=2) { if (G.bel[G.to[i^1]]!=G.bel[G.to[i]] && G.to[i^1]>=1 && G.to[i^1]<=n && G.to[i]>=1 && G.to[i]<=n && !G.w[i]) { ans[++cc]=make_pair(min(G.to[i^1],G.to[i]),max(G.to[i^1],G.to[i])); } } sort(ans+1,ans+cc+1); printf("%d\n",cc); for (ri i=1;i<=cc;i++) printf("%d %d\n",ans[i].first,ans[i].second); return 0; }