博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu3861 强连通+最小路径覆盖
阅读量:6604 次
发布时间:2019-06-24

本文共 2861 字,大约阅读时间需要 9 分钟。

题意:有 n 个点,m 条边的有向图,需要将这些点分成多个块,要求:如果两点之间有路径能够互相到达,那么这两个点必须分在同一块;在同一块内的任意两点相互之间至少要有一条路径到达,即 u 到达 v 或 v 到达 u;每个点都只能存在于单独一个块内。问最少需要划分多少块。

首先,对于如果两点之间能够相互到达则必须在同一块,其实也就是在同一个强连通分量中的点必须在同一块中,所以首先就是强连通缩点。然后在同一块内的任意两点之间要有一条路,那么其实就是对于一块内的强连通分量,至少要有一条路径贯穿所有分量。而这一条路径上的所有强连通分量就可以构成同一块。那么其实我们就是需要找出最少的这样的路径将所有点全部覆盖一遍,就是做一遍最小路径覆盖。

最小路径覆盖数=点数-拆点后的最大匹配数。

1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int maxn=10005; 8 const int maxm=2e5+5; 9 10 int head[2][maxn],point[2][maxm],nxt[2][maxm],size[2]; 11 int n,t,scccnt; 12 int stx[maxn],low[maxn],scc[maxn]; 13 int vis[maxn],match[maxn]; 14 stack
S; 15 16 void init(){ 17 memset(head,-1,sizeof(head)); 18 size[0]=size[1]=0; 19 } 20 21 void add(int a,int b,int c=0){ 22 point[c][size[c]]=b; 23 nxt[c][size[c]]=head[c][a]; 24 head[c][a]=size[c]++; 25 } 26 27 void dfs(int s){ 28 stx[s]=low[s]=++t; 29 S.push(s); 30 for(int i=head[0][s];~i;i=nxt[0][i]){ 31 int j=point[0][i]; 32 if(!stx[j]){ 33 dfs(j); 34 low[s]=min(low[s],low[j]); 35 } 36 else if(!scc[j]){ 37 low[s]=min(low[s],stx[j]); 38 } 39 } 40 if(low[s]==stx[s]){ 41 scccnt++; 42 while(1){ 43 int u=S.top();S.pop(); 44 scc[u]=scccnt; 45 if(s==u)break; 46 } 47 } 48 } 49 50 void setscc(){ 51 memset(stx,0,sizeof(stx)); 52 memset(scc,0,sizeof(scc)); 53 t=scccnt=0; 54 for(int i=1;i<=n;++i)if(!stx[i])dfs(i); 55 for(int i=1;i<=n;++i){ 56 for(int j=head[0][i];~j;j=nxt[0][j]){ 57 int k=point[0][j]; 58 if(scc[i]!=scc[k]){ 59 add(scc[i],scc[k]+scccnt,1); 60 } 61 } 62 } 63 } 64 65 int dfs1(int k){ 66 for(int i=head[1][k];~i;i=nxt[1][i]){ 67 if(!vis[point[1][i]]){ 68 int p=point[1][i]; 69 vis[p]=1; 70 if(match[p]==-1||dfs1(match[p])){ 71 match[p]=k; 72 return 1; 73 } 74 } 75 } 76 return 0; 77 } 78 79 80 int main(){ 81 int T; 82 scanf("%d",&T); 83 while(T--){ 84 int m; 85 scanf("%d%d",&n,&m); 86 init(); 87 while(m--){ 88 int a,b; 89 scanf("%d%d",&a,&b); 90 add(a,b); 91 } 92 setscc(); 93 int ans=0; 94 memset(match,-1,sizeof(match)); 95 for(int i=1;i<=2*scccnt;++i){ 96 memset(vis,0,sizeof(vis)); 97 if(dfs1(i)==1)ans++; 98 } 99 printf("%d\n",scccnt-ans);100 }101 return 0;102 }
View Code

 

转载于:https://www.cnblogs.com/cenariusxz/p/4811732.html

你可能感兴趣的文章
六、nginx搭建织梦DedeCms网站
查看>>
Tair学习小记
查看>>
网卡绑定(服务器&&交换机),缓存服务器Squid架构配置
查看>>
web网站加速之CDN(Content Delivery Network)技术原理
查看>>
Redis 数据结构-字符串源码分析
查看>>
打算写一款框架来提高自己 写个结构吧
查看>>
这世界就是,一些人总在昼夜不停地运转,而另外一些人,起床就发现世界已经变了。...
查看>>
网页设置
查看>>
Ubuntu 操作系统操作
查看>>
vue学习:10、第一个项目,实践中遇到的问题
查看>>
Linux下修改Mysql的用户(root)的密码
查看>>
sed的基本用法
查看>>
一个不错的shell 脚本入门教程
查看>>
JVM、GC相关资料
查看>>
dell r620装cenots7遇到的问题
查看>>
Ansible之playbook的使用
查看>>
ansible模块批量管理
查看>>
redis命令 - GET
查看>>
[Maven问题总结]Jetty9的Maven配置——嵌入式服务器
查看>>
httpd.conf的基本设置
查看>>