[] HAOI2017 new city

Face questions

https://www.luogu.org/problem/P3731

answer

Seeking the cutting edge may be a bipartite graph.

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

 

Guess you like

Origin www.cnblogs.com/shxnb666/p/11291298.html