题目
传送门
Contest Hunter 是个好地方
题解
首先感谢@xp学长的讲解
这是道网络流好题;
原来理解错了题意,然后WA的非常惨。并不是跑一个sb最大流输出方案;
也就是使二分图最大匹配减少的边的数量;
算法如下:
我们先随便跑出一个最大流,在残余网络上进行tarjan找强连通分量缩点,因为在一个无向图中的强联通分量意味这可以相互通达,割掉其中一条边后并不会影响到汇点的路径;结合下图理解一下;
跑完最大流之后图是这个样子;
我们会发现其中1、2 、4、5构成了一个强联通分量
也就是说强联通分量里的边如果删掉之后一定可以通过其他的边到达,此时片可以把他们都看成一个点。
特别需要注意的是源点和汇点也需要跑Tarjan,因为如果有的点因为它的边已经满流而无法通过时,会和源点构成强联通分量。
代码
代码写的非常丑和冗长;
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int maxn=500001;
const int inf=1e9;
int n,m,num,maxflow;
struct Edge{
int next,to,dis,from,id;
}edge[maxn<<1];
int num_edge=-1,head[maxn],cur[maxn],deep[maxn];
int cnt,dfn[maxn],low[maxn],zhan[maxn],top,col[maxn],num_col;
bool ifin[maxn];
queue <int> q;
int read()
{
char ch=getchar(); int now=0,f=1;
while (ch<'0' || ch>'9') {ch=getchar(); if (ch=='-') f=-1;}
while (ch>='0'&&ch<='9')
{
now=(now<<1)+(now<<3)+ch-'0';
ch=getchar();
}
return now*f;
}
void add_edge(int from,int to,int dis,int id)
{
edge[++num_edge].next=head[from];
edge[num_edge].dis=dis;
edge[num_edge].from=from;
edge[num_edge].id=id;
edge[num_edge].to=to;
head[from]=num_edge;
}
void add(int x,int y,