记录编号 401174 评测结果 AAAAAAAAAA
题目名称 [HAOI 2017]新型城市化 最终得分 100
用户昵称 GravatarCydiater 是否通过 通过
代码语言 C++ 运行时间 0.337 s
提交时间 2017-05-01 15:59:14 内存使用 33.50 MiB
显示代码纯文本
#include <bits/stdc++.h>

using namespace std;

#define ll long long 
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define doww(i,j,n)     for(int i=j;i>=n;i--)
#define cmax(a,b)       a=max(a,b)
#define cmin(a,b)       a=min(a,b)
#define pii             pair<int,int>
#define fi              first
#define se              second
#define Auto(i,node)    for(int i=LINK[node];i;i=e[i].next)
#define FILE            "newcity"

const int MAXN=3e5+5;
const int oo=0x3f3f3f3f;

int N,M,S,T,col[MAXN],sta[MAXN],top=0,dfn[MAXN],low[MAXN],dfsclock=0,BCC[MAXN],bccs;
int nxt[MAXN];
pii ed[MAXN];
bool iskey[MAXN],ismat[MAXN],vis[MAXN],used[MAXN];

struct Graph{
        struct edge{
                int y,next;
        }e[MAXN<<1];
        int LINK[MAXN],len;
        inline void insert(int x,int y){
                e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;
        }
        inline void Insert(int x,int y){
        	insert(x,y);
        	insert(y,x);
        }
        void Colit(int node){
        	Auto(i,node)if(!col[e[i].y]){
        		col[e[i].y]=(col[node]==1?-1:1);
        		Colit(e[i].y);
        	}
        }
        void Clear(){
        	memset(LINK,0,sizeof(LINK));
        	len=0;
        }
        void DFS(int node){
        	vis[node]=1;
        	Auto(i,node)if(!vis[e[i].y])
        		DFS(e[i].y);
        }
        void Tarjan(int node){
        	dfn[node]=low[node]=++dfsclock;
        	sta[++top]=node;vis[node]=1;
        	Auto(i,node)if(!dfn[e[i].y]){
        		Tarjan(e[i].y);
        		cmin(low[node],low[e[i].y]);
        	}else if(vis[e[i].y])cmin(low[node],dfn[e[i].y]);
        	if(low[node]==dfn[node]){
        		bccs++;int tmp;
        		do{
        			tmp=sta[top--];
        			BCC[tmp]=bccs;
        			vis[tmp]=0;
        		}while(tmp!=node);
        	}
        }
}G1,G2;


namespace Maxflow{
        struct edge{
                int y,next,flow,rev;
        }e[MAXN<<1];
        int LINK[MAXN],len,level[MAXN];
        deque<int>q;
        inline void insert(int x,int y,int flow,int rev){
                e[++len].next=LINK[x];LINK[x]=len;
                e[len].y=y;e[len].flow=flow;e[len].rev=len+rev;
        }
        inline void Insert(int x,int y,int flow){
                insert(x,y,flow,1);
                insert(y,x,0,-1);
        }
        bool makelevel(){
        	memset(level,-1,sizeof(level));
        	q.push_back(S);level[S]=0;
        	while(!q.empty()){
        		int node=q.front();q.pop_front();
        		Auto(i,node)if(level[e[i].y]==-1&&e[i].flow){
        			level[e[i].y]=level[node]+1;
        			q.push_back(e[i].y);
        		}
        	}
        	return level[T]!=-1;
        }
        int addflow(int node,int flow){
        	if(node==T||!flow)return flow;
        	int maxflow=0,d;
        	Auto(i,node)if(e[i].flow&&level[e[i].y]==level[node]+1)
        		if(d=addflow(e[i].y,min(e[i].flow,flow-maxflow))){
        			maxflow+=d;
        			e[i].flow-=d;
        			e[e[i].rev].flow+=d;
        		}
        	if(!maxflow)level[node]=-1;
        	return maxflow;
        }
        void Dinic(){
        	int ans=0,d;
        	while(makelevel())
        		while(d=addflow(S,oo))
        			ans+=d;
        }
        void Build(){
           	Auto(i,S)if(e[i].flow==0)ismat[e[i].y]=1;
        	Auto(i,T)if(e[e[i].rev].flow==0)ismat[e[i].y]=1;
        	up(node,1,N)if(col[node]==-1)Auto(i,node)if(e[i].y!=S){
        		if(e[i].flow==0){
        			G2.insert(e[i].y,node);
        			nxt[node]=e[i].y;
        		}
        		else		G2.insert(node,e[i].y);
        	}
        	vis[S]=vis[T]=1;
        	up(i,1,N)if(col[i]==-1&&!ismat[i]&&!vis[i])
        		G2.DFS(i);
        	memcpy(used,vis,sizeof(used));
        	memset(vis,0,sizeof(vis));
        	G2.Clear();
        	up(node,1,N)if(col[node]==1)Auto(i,node)if(e[i].y!=T){
           		if(e[e[i].rev].flow==0){
           			G2.insert(e[i].y,node);
           			nxt[node]=e[i].y;
           		}
        		else			G2.insert(node,e[i].y);     	
        	}
        	vis[S]=vis[T]=1;
        	up(i,1,N)if(col[i]==1&&!ismat[i]&&!vis[i])
        		G2.DFS(i);
   		up(i,1,N)used[i]|=vis[i];
        	up(i,1,N)if(!used[i]&&ismat[i])iskey[i]=1;     	
        }
}

namespace solution{
        void Prepare(){
                scanf("%d%d",&N,&M);
                up(i,1,M){
                        int x,y;
                        scanf("%d%d",&x,&y);
                        if(x>y)swap(x,y);
                        ed[i]=make_pair(x,y);
                        G1.Insert(x,y);
                }
                sort(ed+1,ed+M+1);
                S=N+1;T=N+2;
                up(i,1,N)if(!col[i])G1.Colit(i);
                up(i,1,M){
                	int x=ed[i].fi,y=ed[i].se;
                	if(col[x]==1)swap(x,y);
                	Maxflow::Insert(x,y,1);
                }
                up(i,1,N){
                	if(col[i]==-1)		Maxflow::Insert(S,i,1);
                	else if(col[i]==1)	Maxflow::Insert(i,T,1);
                }
                Maxflow::Dinic();//转化为二分图然后跑最大匹配
                Maxflow::Build();//重新建图
        }
        void Solve(){
        	// 求出所有关键点
        	up(i,1,N)if(!dfn[i])G2.Tarjan(i);
        	int ans=0;
        	up(i,1,M){
        		int x=ed[i].fi,y=ed[i].se;
        		if(nxt[x]!=y||BCC[x]==BCC[y])continue;
        		if(iskey[x]||iskey[y])ans++;
        	}
        	cout<<ans<<endl;
        	up(i,1,M){
        		int x=ed[i].fi,y=ed[i].se;
        		if(nxt[x]!=y||BCC[x]==BCC[y])continue;
        		else if(iskey[x]||iskey[y])
        			printf("%d %d\n",x,y);
        	}
        }
}

int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	using namespace solution;
	Prepare();
	Solve();
	return 0;
}