P2764 最小路径覆盖问题
题解:最小路径覆盖等于点数-匹配数。网络流或者km跑一下二分图记录路径就可以解决
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const double Pi=3.14159265; const int N=1e5+5; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; int n,m,s,t; int head[100010],to[N],cur[100010],nx[N]; int cap[N]; int tot=0; void add(int x,int y,int c){ to[tot]=y; nx[tot]=head[x]; cap[tot]=c; head[x]=tot++; to[tot]=x; nx[tot]=head[y]; cap[tot]=0; head[y]=tot++; } void init(int n){ tot=0; memset(head,-1,sizeof(head)); } int d[N]; int NX[N]; int bfs(){ memset(d,-1,sizeof(d)); queue<int>q; q.push(s); d[s]=1; while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];~i;i=nx[i]){ int v=to[i]; if(d[v]==-1&&cap[i]>0){ d[v]=d[u]+1; q.push(v); } } } return d[t]!=-1; } int dfs(int s,int a){ if(s==t||a==0)return a; int flow=0,f; for(int &i=cur[s];~i;i=nx[i]){ int v=to[i]; if(d[s]+1==d[v] && cap[i]>0 && (f=dfs(v,min(a,cap[i])))>0){ flow+=f; cap[i]-=f; cap[i^1]+=f; NX[s]=v; a-=f; if(a==0)break; } } return flow; } int dinic(){ int ans=0; while(bfs()){ for(int i=0;i<=t;i++)cur[i]=head[i]; while(int di=dfs(s,INF)){ ans+=di; } } return ans; } int dee[N]; int vis[N]; int main(){ t=2000; s=0; int n,m; scanf("%d%d",&n,&m); init(n); for(int i=1;i<=m;i++){ int l,r; scanf("%d%d",&l,&r); add(l,1000+r,1); } for(int i=1;i<=n;i++){ add(s,i,1); add(i+1000,t,1); } int tt=n-dinic(); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ if(!vis[i]){ if(NX[i]){ int j=i; while (j!=t&&j!=s&&!vis[j]) { vis[j]=1; if(NX[j]>1000)NX[j]-=1000; printf("%d ",j); j=NX[j]; } } else{ printf("%d ",i); }cout<<endl; } } cout<<tt<<endl; return 0; } /* */