Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1091 Accepted Submission(s): 404
强连通缩点+二分匹配
求最小路径覆盖=(顶点数 - 最大匹配数);
题目上说的很清楚,What’s more, for each pair of city (u, v), if there is one way to go from u to v and go from v to u, (u, v) have to belong to a same state
,所以显然要先缩点,之后用二分匹配求最小路径覆盖,思路很清晰!
#include
#include
#include
#include
using namespace std;
#define max_n 5005
#define max_e 250002
#define inf 99999999
int stack[max_n],top;//栈
int isInStack[max_n];//是否在栈内
int low[max_n],dfn[max_n],tim;//点的low,dfn值;time从1开始
int node_id;//强连通分量的个数
int head[max_n],s_edge;//邻接表头 s_edge从1开始
int gro_id[max_n];//记录某个点属于哪个强连通分量
int n,m;
bool vis[max_n];
int match[max_n];
vector vec[max_n];//边的后节点存储
struct Node
{
int to;
int next;
} edge[max_e];
int head1[max_n];
int NE;
struct Node1
{
int from;
int to;
int next;
} edge1[max_e];
void init()//初始化
{
s_edge=0;//存储
memset(head,0,sizeof(head));
memset(edge,0,sizeof(edge));
top=0;//tarjian初始化
tim=0;
node_id=0;
memset(isInStack,0,sizeof(isInStack));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
NE=0;
memset(head1,-1,sizeof(head1));
memset(match,-1,sizeof(match));
}
void addedge(int u,int v)
{
s_edge++;
edge[s_edge].to=v;
edge[s_edge].next=head[u];
head[u]=s_edge;
}
void add(int u,int v)
{
edge1[NE].from=u;
edge1[NE].to=v;
edge1[NE].next=head1[u];
head1[u]=NE++;
}
int min(int a,int b)
{
if(a>t;
while(t--)
{
scanf("%d %d",&n,&m);
init();
for(int i=1; i<=n; i++)
vec[i].clear();
for(int i = 0 ; i