前言
一两年前见过没打…
题目
一个
D
A
G
DAG
DAG,问最多放置多少个点使得两两之间无法到达(单向)?
数据范围
n
<
=
200
,
m
<
=
30000
n<=200,m<=30000
n<=200,m<=30000
思路
可以看作可相交最小路径覆盖数,为什么呢,因为此时一条路径上必存在一个点使得其他路径均无法到达,否则可以删去这条路径,因为这条路径上的边都被其他路径瓜分了…
然后考虑两点之间到达情况,可由不相交最小路径覆盖=点数-最大匹配拓展,Floyd传递闭包后使得可以相交,匈牙利跑一遍即可
代码
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
#define ULL unsigned long long
using namespace std;
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f*x;
}
#define MAXN 200
vector<int> G[2*MAXN+5];
inline void Addedge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
return ;
}
bool f[MAXN+5][MAXN+5];
void Floyd(int n){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]|=f[i][k]&f[k][j];
return ;
}
int ma[2*MAXN+5],vis[2*MAXN+5];
bool DFS(int u){
for(int i=0;i<int(G[u].size());i++){
int v=G[u][i];
if(vis[v]) continue;
vis[v]=1;
if(!ma[v]||DFS(ma[v])){
ma[v]=u,ma[u]=v;
return 1;
}
}
return 0;
}
int main(){
int n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
f[u][v]=1;
}
Floyd(n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(f[i][j])
Addedge(i,n+j);
int ans=0;
for(int i=1;i<=n;i++)
if(!ma[i]){
memset(vis,0,sizeof(vis));
ans+=DFS(i);
}
printf("%d\n",n-ans);
return 0;
}