最小路径覆盖问题
有点蠢。。。结论题。。。(还是魔术球问题的一个部分)
DAG最小路径覆盖直接拆点建二分图然后顶点数-最大匹配就可以了。。。
其他相关结论见魔术球问题(大雾)
大体相当于“找出路”。
蠢蠢的还RE了一发QAQ
附代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 20021225
#define ll long long
using namespace std;
struct edge{int to,lt,f;}e[20000];
int in[400],cnt=1,s,t,dep[400],n,m;
queue<int> que;
void add(int x,int y,int f)
{
e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;in[x]=cnt;
e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;in[y]=cnt;
}
bool bfs()
{
while(!que.empty()) que.pop();
memset(dep,0,sizeof(dep));
dep[s]=1;que.push(s);
while(!que.empty())
{
int x=que.front();que.pop();
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(!dep[y]&&e[i].f)
{
dep[y]=dep[x]+1;
if(y==t) return 1;
que.push(y);
}
}
}
return 0;
}
int nxt[600];
int dfs(int x,int flow)
{
if(x==t||!flow) return flow;
int cur=flow;
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(dep[y]==dep[x]+1&&e[i].f)
{
int tmp=dfs(y,min(e[i].f,cur));
if(tmp) nxt[x]=y-n;
cur-=tmp;e[i].f-=tmp;e[i^1].f+=tmp;
if(!cur) return flow;
}
}
dep[x]=-1;return flow-cur;
}
int dinic()
{
int ans=0;
while(bfs()) ans+=dfs(s,inf);
return ans;
}
bool vis[600];
int main()
{
int x,y;
scanf("%d%d",&n,&m);
s=2*n+1;t=s+1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add(x,y+n,1);
}
for(int i=1;i<=n;i++)
add(s,i,1),add(i+n,t,1);
dinic();int ans=0;
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
while(i&&i!=t-n)
{
printf("%d ",i);
vis[i]=1;i=nxt[i];
}
printf("
");
ans++;
}
}
printf("%d
",ans);
return 0;
}