网络流24题,题意是在有向无环图中求最小路径覆盖。
蒟蒻想不出。。看了题解才明白。。
建图思路:
首先,网络上是没有流的。每个节点自成一家。
然后。。考虑一个类似合并的操作:每有一条有向边,就可以考虑是否合并这两个节点,这个可以用网络流调整得出答案。
最后要输出的 答案,就是原来节点数n-合并的次数
具体实现:
对于序号为i的节点,拆成Xi与Yi两个部分
1、由s向所有Xi连一条流量为1的边
2、由所有Yi向t连一条流量为1的边
3、每有一条边(i,j)就从Xi向Yj连一条流量为1的边。若在网络流增广时使用了这条边,就说明两个节点合并。
答案很好统计。。
总结:
1、在做dinic的时候,又犯了一些错误,导致Wa了两次
2、还是不容易想到网络流的建图思路。。。
hhhhhhhhhhhhhhhhhhhhhhh
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cctype>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iomanip>
#include<sstream>
#include<cstdlib>
#include<ctime>
#include<list>
#include<deque>
#include<bitset>
#include<fstream>
#define ld double
#define ull unsigned long long
#define ll long long
#define pii pair<int,int >
#define iiii pair<int,pii >
#define mp make_pair
#define INF 1000000000
#define MOD 1000000007
#define rep(i,x) for(int (i)=0;(i)<(x);(i)++)
inline int getint()
{
int x=0,p=1;char c=getchar();
while (c<=32)c=getchar();
if(c==45)p=-p,c=getchar();
while (c>32)x=x*10+c-48,c=getchar();
return x*p;
}
using namespace std;
//
const int maxn=500+5;
const int s=400;
const int t=401;
struct E
{
int to,val,rev;
};
int n,m,res,dis[maxn],iter[maxn],ord[maxn],pre[maxn];
vector<E>G[maxn];
vector<int>ans[maxn];
queue<int>qu;
//
inline void faddedge(int x,int y)
{
G[x].emplace_back((E){y,1,(int)G[y].size()});
G[y].emplace_back((E){x,0,(int)G[x].size()-1});
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
qu.push(s);dis[s]=0;
while (!qu.empty())
{
int u=qu.front();
qu.pop();
rep(i,G[u].size())
{
E e=G[u][i];
if(e.val>0&&dis[e.to]<0)
{
dis[e.to]=dis[u]+1;
qu.push(e.to);
}
}
}
return (dis[t]>0);
}
int dfs(int v,int val)
{
if(v==t)return val;
while (iter[v]<G[v].size())
{
E &e=G[v][iter[v]];
if(dis[e.to]>dis[v]&&e.val>0)
{
int ans=dfs(e.to,min(val,e.val));
if(ans>0)
{
e.val-=ans;
G[e.to][e.rev].val+=ans;
return ans;
}
}
iter[v]++;
}
return 0;
}
void dinic()
{
while (bfs())
{
memset(iter,0,sizeof(iter));
int f;
while (f=dfs(s,INF));
}
}
void sufsolve()
{
memset(pre,-1,sizeof(pre));
memset(ord,-1,sizeof(ord));
rep(i,n)rep(j,G[i].size())
{
E e=G[i][j];
if(e.val==0&&e.to>=n&&e.to<2*n)pre[e.to-n]=i;
}
int cnt=0;
while (1)
{
rep(i,n)
{
if(pre[i]==-1)
{
ans[res++].emplace_back(i);
ord[i]=res-1;
cnt++;
}
else if(ord[pre[i]]>=0)
{
ans[ord[pre[i]]].emplace_back(i);
ord[i]=ord[pre[i]];
cnt++;
}
}
if(cnt==n)break;
}
rep(i,res)
{
rep(j,ans[i].size())printf("%d ",ans[i][j]+1);
putchar('\n');
}
printf("%d\n",res);
}
int main()
{
n=getint();m=getint();
rep(i,n)
{
faddedge(s,i);
faddedge(i+n,t);
}
rep(i,m)
{
int x=getint()-1,y=getint()-1;
faddedge(x,y+n);
}
dinic();
sufsolve();
return 0;
}