题意:有多少条,一定被包含在最大匹配里面
sol.
60分,断掉每一条边,看是否任然满流,若不满流,则必须出现在最大匹配里面
考虑满分做法
直接如果一条边,在残余网络的一个强连通分量里面,是可以不选的
就做完了
#include<bits/stdc++.h>
#define MAXN 10005
#define MAXM 200005
#define INF 0x3f3f3f3f
using namespace std;
int n,m;
int color[MAXN],vis[MAXN],S,T;
vector<int>G[MAXN];
int h[MAXN],tot,G1[MAXM],G2[MAXM];
int le,ans_yl;
pair<int , int> t[MAXN];
struct node{int from,to,next,rest;}e[MAXM << 1];
void add(int x , int y , int z){
tot++;
e[tot].from = x;
e[tot].to = y;
e[tot].rest = z;
e[tot].next = h[x];
h[x] = tot;
}
bool cmp(pair<int , int> A , pair<int , int> B){
if(A.first == B.first)return A.second < B.second;
return A.first < B.first;
}
int dis[MAXN];
queue<int>q;
bool bfs(){
memset(vis , 0 , sizeof(vis));
memset(dis , 0x3f , sizeof(dis));
while(!q.empty())q.pop();q.push(S) , dis[S] = 0 , vis[S] = 1;int now;
while(!q.empty()){
now = q.front() , q.pop() , vis[now] = 0;
for(int i = h[now] ; i != (-1) ; i = e[i].next){
if(!e[i].rest)continue;
if(dis[e[i].to] <= dis[now] + 1)continue;
dis[e[i].to] = dis[now] + 1;
if(!vis[e[i].to])vis[e[i].to] = 1 , q.push(e[i].to);
}
}
return (dis[T] < INF);
}
int dfs(int now , int low){
if(now == T)return low;
int used = low , res;
for(int i = h[now] ; i != (-1) ; i = e[i].next){
if(!e[i].rest)continue;
if(dis[e[i].to] != dis[now] + 1)continue;
if(res = dfs(e[i].to , min(used , e[i].rest))){
used -= res;
e[i].rest -= res;
e[i ^ 1].rest += res;
if(!used)break;
}
}
return low - used;
}
int dinic(){
int zz = 0;
while(bfs()){
zz = zz + dfs(S , INF);
}
return zz;
}
int init(int dx){
memset(h , -1 , sizeof(h)) , tot = (-1);
int x,y;
for(int i = 1 ; i <= m ; i++){
if(i == dx)continue;
if(color[G1[i]] == 1)swap(G1[i] , G2[i]);
x = G1[i] , y = G2[i];
add(x , y , 1) , add(y , x , 0);
}
for(int i = 1 ; i <= n ; i++){
if(color[i] == 0)add(S , i , 1) , add(i , S , 0);
else add(i , T , 1) , add(T , i , 0);
}
return dinic();
}
void ycl(int now , int fa){
vis[now] = 1;
for(auto v : G[now]){
if(v == fa)continue;
if(vis[v])continue;
color[v] = color[now] ^ 1;
ycl(v , now);
}
}
int low[MAXN],dfn[MAXN],dex,belong[MAXN],js;
stack<int>q2;
void tarjan(int now , int fa){
low[now] = dfn[now] = ++dex , vis[now] = 1;
q2.push(now);
for(int i = h[now] ; i != (-1) ; i = e[i].next){
if(e[i].to == fa)continue;
if(!e[i].rest)continue;
if(!dfn[e[i].to]){
tarjan(e[i].to , now);
low[now] = min(low[now] , low[e[i].to]);
}
else if(!belong[e[i].to])low[now] = min(low[now] , dfn[e[i].to]);
}
if(dfn[now] == low[now]){
int u;js++;
do{
u = q2.top() , q2.pop() , vis[u] = 0;
belong[u] = js;
}while(u != now);
}
}
int main(){
scanf("%d%d" , &n , &m) , S = 0 , T = n + 1;
for(int i = 1 ; i <= m ; i++)scanf("%d%d" , &G1[i] , &G2[i]) , G[G1[i]].push_back(G2[i]) , G[G2[i]].push_back(G1[i]);
for(int i = 1 ; i <= n ; i++)if(!vis[i])ycl(i , i);
ans_yl = init(0);
memset(vis , 0 , sizeof(vis));
for(int i = S ; i <= T ; i++){
if(!dfn[i])tarjan(i , i);
}
for(int i = 0 ; i <= tot ; i = i + 2){
if(e[i].from == S || e[i].to == S)continue;
if(e[i].from == T || e[i].to == T)continue;
if(e[i].rest)continue;
if(belong[e[i].from] == belong[e[i].to])continue;
le++ , t[le].first = e[i].from , t[le].second = e[i].to;
if(t[le].first > t[le].second)swap(t[le].first , t[le].second);
}
sort(t + 1 , t + 1 + le , cmp);
cout<<le<<endl;
for(int i = 1 ; i <= le ; i++){
cout<<t[i].first<<" "<<t[i].second<<endl;
}
}