HPU图论专项(graph)【拓扑--二分图--最小生成树---树的直径---并查集--奇偶树---最小环---强联通】
对于下面的模板题不懂的话--请自学模板---
在我的博客里可能会有讲解---
重点可看:我的ACM历程
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
今天,它终于当上了梦寐以求的体育课老师。第一次课上,它发现一个有趣的事情。在上课之前,所有同学要排成一列, 假设最开始每个人有一个唯一的ID,从1到N,在排好队之后,每个同学会找出包括自己在内的前方所有同学的最小ID,作为自己评价这堂课的分数。麻烦的是,有一些同学不希望某个(些)同学排在他(她)前面,在满足这个前提的情况下,新晋体育课老师——度度熊,希望最后的排队结果可以使得所有同学的评价分数和最大。
Input
对于每组数据,第一行输入两个整数N和M (1 \leq N \leq 100000, 0 \leq M \leq 100000),分别表示总人数和某些同学的偏好。
接下来M行,每行两个整数A 和B(1 \leq A, B \leq N),表示ID为A的同学不希望ID为B的同学排在他(她)之前。你可以认为题目保证至少有一种排列方法是符合所有要求的。
Output
Sample Input
3 1 0 2 1 1 2 3 1 3 1
Sample Output
1 2 6
拓扑水题---
代码:
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int head[120000];
struct node{int to,next;
}dian[120000];
int shu[120000];
int main()
{int t;scanf("%d",&t);for (int ca=1;ca<=t;ca++){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++){head[i]=-1;shu[i]=0;}int a,b;while (m--){scanf("%d%d",&a,&b);dian[m].to=b;dian[m].next=head[a];head[a]=m;shu[b]++;}priority_queue<int> que;for (int i=1;i<=n;i++)if (shu[i]==0)que.push(i);__int64 ans=0;int lp=120000000;while (!que.empty()){a=que.top();que.pop();lp=min(lp,a);ans+=lp;for (int j=head[a];j!=-1;j=dian[j].next){b=dian[j].to;shu[b]--;if (shu[b]==0)que.push(b);}}printf("%I64d\n",ans);}return 0;
}
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
1<=N 和M<=500.接下来的K行,每行有两个数,分别表示女生Ai愿意和男生Bj做partner。最后一个0结束输入。
Output
Sample Input
6 3 3 1 1 1 2 1 3 2 1 2 3 3 1 0
Sample Output
3
二分图--模板题---
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int k,n,m;
int head[520];
int fer[520];
bool guo[520];
struct node{int to,next;
}dian[1200];
int find(int xx)
{for (int i=head[xx];i!=-1;i=dian[i].next){int v=dian[i].to;if (guo[v]){guo[v]=false;if (!fer[v]){fer[v]=xx;return true;}else if (find(fer[v])){fer[v]=xx;return true;}}}return false;
}
int main()
{while (scanf("%d",&k),k){scanf("%d%d",&m,&n);memset(fer,0,sizeof(fer));memset(dian,0,sizeof(dian));for (int i=0;i<=510;i++)head[i]=-1;int a,b;for (int i=0;i<k;i++){scanf("%d%d",&a,&b);dian[i].to=b;dian[i].next=head[a];head[a]=i;}int s=0;for (int i=1;i<=m;i++){memset(guo,true,sizeof(guo));if (find(i))s++;}printf("%d\n",s);}return 0;
}
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
现在给出老 Jack农田的数据,你需要告诉老 Jack 在保证所有农田全部可连通灌溉的情况下,最少还需要再购进多长的管道。另外,每块农田都是方形等大的,一块农田只能跟它上下左右四块相邻的农田相连通。
Input
输入包含若干组测试数据,处理到文件结束。每组测试数据占若干行,第一行两个正整数 ,代表老 Jack 有N行*M列个农田。接下来 N 行,每行 M 个数字,代表每块农田的高度,农田的高度不会超过100。数字之间用空格分隔。
Output
第一行输出:"Case #i:"。i代表第i组测试数据。
第二行输出 1 个正整数,代表老 Jack 额外最少购进管道的长度。
Sample Input
2 4 3 9 12 4 7 8 56 32 32 43 21 12 12 2 3 34 56 56 12 23 4
Sample Output
Case #1: 82 Case #2: 74
最小生成树---
建边时:重复的变只需要记录一次---(否则超内存)
即只记每个点右边和下边的点---
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL __int64
int n,m;
int xx[2]={0,1};
int yy[2]={1,0};
LL map[1010][1010];
int fer[1001000];
struct node{int a,b,chang;
}lu[2000100];
bool cmp(node xx,node yy)
{return xx.chang<yy.chang;
}
int find(int xx)
{if (xx==fer[xx])return xx;return fer[xx]=find(fer[xx]);
}
int main()
{int t;scanf("%d",&t);for (int ca=1;ca<=t;ca++){scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)scanf("%I64d",&map[i][j]);int now,qian;int x,y,kp=0;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){now=i*m-m+j;for (int k=0;k<2;k++){x=i+xx[k];y=j+yy[k];if (x&&y&&x<=n&&y<=m){lu[kp].a=now;lu[kp].b=x*m-m+y;lu[kp].chang=abs(map[i][j]-map[x][y]);kp++;}}}}sort(lu,lu+kp,cmp);for (int i=1;i<=n*m;i++)fer[i]=i;LL ans=0;now=n*m;for (int i=0;i<kp;i++){x=find(lu[i].a);y=find(lu[i].b);if (x!=y){ans+=lu[i].chang;fer[x]=y;now--;if (now==1)break;}}printf("Case #%d:\n%I64d\n",ca,ans);}return 0;
}
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
束。
Output
Sample Input
3 3 1 2 1 3 2 3 3 2 1 2 2 3 0
Sample Output
1 0
欧拉回路模板题--
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int ru[1400];
int fer[1400];
int find(int xx)
{if (xx==fer[xx])return xx;return fer[xx]=find(fer[xx]);
}
int main()
{while (scanf("%d",&n),n){scanf("%d",&m);memset(ru,0,sizeof(ru));for (int i=1;i<=n;i++)fer[i]=i;int a,b,aa,bb;while (m--){scanf("%d%d",&a,&b);ru[a]++;ru[b]++;aa=find(a);bb=find(b);if (aa!=bb)fer[aa]=bb;}int s=0,ss=0;for (int i=1;i<=n;i++){if (find(i)==i)s++;if (ru[i]%2!=0)ss++;}if (ss||s!=1)printf("0\n");elseprintf("1\n");}return 0;
}
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu
Description
Input
The labyrinth is designed in such a way that there is exactly one path between any two free blocks. Consequently, if we find the proper hooks to connect, it is easy to find the right path connecting them.
Output
Sample Input
2 3 3 ### #.# ### 7 6 ####### #.#.### #.#.### #.#.#.# #.....# #######
Sample Output
Maximum rope length is 0. Maximum rope length is 8.
Hint
If you use recursion, maybe stack overflow. and now C++/c 's stack size is larger than G++/gcc
树的直径---:
思路:
每一个联通的区域都可以看做是一个树---
然后两次dfs--求树的直径
代码:
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
bool fafe[1010][1010];
char ch[1010][1010];
int shu[1001000],kp;
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int n,m;
int ii,jj;
struct node{int x,y;int step;
}now,qian;
int dfs(int i,int j)
{queue<node> que;now.x=i;now.y=j;now.step=0;que.push(now);fafe[i][j]=false;int a,b,ans;while (!que.empty()){now=que.front();que.pop();ii=now.x;jj=now.y;ans=now.step;for (int k=0;k<4;k++){a=ii+xx[k];b=jj+yy[k];if (a>0&&b>0&&a<=n&&b<=m&&ch[a][b]=='.'&&fafe[a][b]){fafe[a][b]=false;qian.x=a;qian.y=b;qian.step=now.step+1;que.push(qian);}}}return ans;
}
void bfs(int i,int j)
{ch[i][j]='#';int a,b;for (int k=0;k<4;k++){a=i+xx[k];b=j+yy[k];if (a>0&&b>0&&a<=n&&b<=m&&ch[a][b]=='.'){bfs(a,b);}}
}
int main()
{int t;scanf("%d",&t);while (t--){scanf("%d%d",&m,&n);for (int i=1;i<=n;i++)scanf("%s",ch[i]+1);kp=0;int sss=0,ss;for (int i=1;i<=n;i++){for (int j=1;j<=m;j++){if (ch[i][j]=='.'){memset(fafe,true,sizeof(fafe));dfs(i,j);memset(fafe,true,sizeof(fafe));ss=dfs(ii,jj);sss=max(sss,ss);bfs(i,j);}}}printf("Maximum rope length is %d.\n",sss);}return 0;
}
Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
Input
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。
Output
Sample Input
3 3 1 2 1 2 3 1 1 3 1 3 3 1 2 1 1 2 3 2 3 1
Sample Output
3 It's impossible.
求图中的最小环:
思路1:对于每一边A-B进行覆盖处理:
将此边覆盖--然后求A到B的最短距离:
时间复杂度为:O(n*n*m)
思路2:
Floyd的一点点变形求最小环---【模板】----
时间复杂度:O(n*n*n)
下面用的是思路1---
思路2正在学---
代码“:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int map[110][110];
int dis[110];
bool fafe[110];
int disk(int xx,int yy)
{int ans=-1;memset(fafe,true,sizeof(fafe));for (int i=1;i<=n;i++)dis[i]=map[xx][i];fafe[xx]=false;fafe[yy]=false;while (1){int mi=0xff3f3f,ii=-1;for (int i=1;i<=n;i++){if (fafe[i]&&dis[i]<mi){mi=dis[i];ii=i;}}if (ii==-1)break;fafe[ii]=false;if (map[ii][yy]<10000){if (ans==-1)ans=mi+map[ii][yy];elseans=min(ans,mi+map[ii][yy]);}for (int i=1;i<=n;i++){if (fafe[i]&&map[ii][i]+dis[ii]<dis[i])dis[i]=dis[ii]+map[ii][i];}}return ans;
}
int main()
{while (~scanf("%d%d",&n,&m)){int a,b,c;memset(map,0xff3f3f,sizeof(map));for (int i=0;i<m;i++){scanf("%d%d%d",&a,&b,&c);map[a][b]=map[b][a]=min(c,map[a][b]);}int s=-1;for (int i=1;i<n;i++){for (int j=i+1;j<=n;j++){if (map[i][j]<100000){int lp=disk(i,j);if (lp!=-1){lp+=map[i][j];if (s==-1)s=lp;elses=min(s,lp);}}}}if (s==-1)printf("It's impossible.\n");elseprintf("%d\n",s);}return 0;
}
Time Limit:500MS Memory Limit:32768KB 64bit IO Format:%lld & %llu
Description
Nowadays the one-way traffic is introduced all over the world in order to improve driving safety and reduce traffic jams. The government of Dhaka Division decided to keep up with new trends. Formerly all n cities of Dhaka were connected by n two-way roads in the ring, i.e. each city was connected directly to exactly two other cities, and from each city it was possible to get to any other city. Government of Dhaka introduced one-way traffic on all n roads, but it soon became clear that it's impossible to get from some of the cities to some others. Now for each road is known in which direction the traffic is directed at it, and the cost of redirecting the traffic. What is the smallest amount of money the government should spend on the redirecting of roads so that from every city you can get to any other?
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case starts with a blank line and an integer n (3 ≤ n ≤ 100) denoting the number of cities (and roads). Next n lines contain description of roads. Each road is described by three integers ai, bi, ci (1 ≤ ai, bi ≤ n, ai ≠ bi, 1 ≤ ci ≤ 100) - road is directed from city ai to city bi, redirecting the traffic costsci.
Output
For each case of input you have to print the case number and the smallest amount of money the government should spend on the redirecting of roads so that from every city you can get to any other.
Sample Input
4
3
1 3 1
1 2 1
3 2 1
3
1 3 1
1 2 5
3 2 1
6
1 5 4
5 3 8
2 4 15
1 6 16
2 3 23
4 6 42
4
1 2 9
2 3 8
3 4 7
4 1 5
Sample Output
Case 1: 1
Case 2: 2
Case 3: 39
Case 4: 0
题意:
N个点--N条路----
路是有向路--但是路的方向可以改变---(需要消耗金币)
求最小需要多少钱使N个点强连通
--没有无解的情况---所以N条边让N个点形成了一个环--(只有边的方向不确定---)
这样的话---怎么样才可以强连通呢???
1:顺时针
2:逆时针
想想是为什么-----------
我们可以求出任意一种方向所需要的金钱
另外一个方向所需的金钱个数就是总钱-第一个金钱总和
我们取最小值即可---
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int a,b,c;
}lu[105];
int fer[105];
int main()
{int t;scanf("%d",&t);for (int ca=1;ca<=t;ca++){int n;scanf("%d",&n);int a,b,c,s=0;for (int i=0;i<n;i++){scanf("%d%d%d",&lu[i].a,&lu[i].b,&lu[i].c);s+=lu[i].c;}int kp=1;int s1=0;while (n--){// printf(" %d 66\n",kp);for (int i=0;i<=n;i++){// printf("%d %d 0.0.0.\n",lu[i].a,lu[i].b);if (lu[i].a==kp){kp=lu[i].b;lu[i]=lu[n];break;}if (lu[i].b==kp){kp=lu[i].a;s1+=lu[i].c;lu[i]=lu[n];break;}}// printf(" %d 99\n",kp);}// printf("%d %d 66\n",s,s1);int ss=min(s1,s-s1);printf("Case %d: %d\n",ca,ss);}return 0;
}
Description
The Vampires and Lykans are fighting each other to death. The war has become so fierce that, none knows who will win. The humans want to know who will survive finally. But humans are afraid of going to the battlefield.
So, they made a plan. They collected the information from the newspapers of Vampires and Lykans. They found the information about all the dual fights. Dual fight means a fight between a Lykan and a Vampire. They know the name of the dual fighters, but don't know which one of them is a Vampire or a Lykan.
So, the humans listed all the rivals. They want to find the maximum possible number of Vampires or Lykans.
Input
Input starts with an integer T (≤ 10), denoting the number of test cases.
Each case contains an integer n (1 ≤ n ≤ 105), denoting the number of dual fights. Each of the next n lines will contain two different integers u v (1 ≤ u, v ≤ 20000) denoting there was a fight between u and v. No rival will be reported more than once.
Output
For each case, print the case number and the maximum possible members of any race.
Sample Input
2
2
1 2
2 3
3
1 2
2 3
4 2
Sample Output
Case 1: 2
Case 2: 3
Hint
Dataset is huge, use faster I/O methods.
Developed and Maintained by
JANE ALAM JAN |
Copyright © 2012
LightOJ, Jane Alam Jan |
并查集+奇偶树----
我们可以将人看成一个一个的点---
对决看成边----
题意就是求:每个联通块的奇偶集合中最大集合的总和了----
用并查集求出每个联通块----
然后求每个联通块求出奇偶集合各自的值----
代码“:
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
struct node{int to,next;
}lu[200200];
int head[20010];
int fer[20010];
bool fafe[20010];
struct nn{int step,to;
}now,qian;
int find(int xx)
{if (xx==fer[xx])return xx;return fer[xx]=find(fer[xx]);
}
int dfs(int xx)
{int qi=0,ou=0;queue<nn> que;now.step=1;now.to=xx;que.push(now);fafe[xx]=false;while (!que.empty()){now=que.front();que.pop();if (now.step%2==0)ou++;else qi++;int xx=now.to;for (int i=head[xx];i!=-1;i=lu[i].next){int y=lu[i].to;if (fafe[y]){qian.step=now.step+1;qian.to=y;fafe[y]=false;que.push(qian);}}}return max(ou,qi);
}
int main()
{int t;scanf("%d",&t);for (int ca=1;ca<=t;ca++){int n;scanf("%d",&n);for (int i=1;i<=20000;i++){head[i]=-1;fer[i]=i;fafe[i]=false;}int a,b;for (int i=0;i<n;i++){scanf("%d%d",&a,&b);fer[find(a)]=find(b);lu[2*i].to=b;lu[2*i].next=head[a];head[a]=2*i;lu[2*i+1].to=a;lu[i*2+1].next=head[b];head[b]=i*2+1;fafe[a]=true;fafe[b]=true;}int ans=0;for (int i=1;i<=20000;i++){if (fafe[i]&&fer[i]==i){ans+=dfs(i);}}printf("Case %d: %d\n",ca,ans);}return 0;
}
HPU图论专项(graph)【拓扑--二分图--最小生成树---树的直径---并查集--奇偶树---最小环---强联通】相关推荐
- 求树的直径+并查集(bfs,dfs都可以)hdu4514
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...
- 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)
题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...
- 暑期集训5:并查集 线段树 练习题G: HDU - 1754
2018学校暑期集训第五天--并查集 线段树 练习题G -- HDU - 1754 I Hate It 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让 ...
- 暑期集训5:并查集 线段树 练习题F: HDU - 1166
2018学校暑期集训第五天--并查集 线段树 练习题F -- HDU - 1166 敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A ...
- 暑期集训5:并查集 线段树 练习题B: HDU - 1213
2018学校暑期集训第五天--并查集 线段树 练习题B -- HDU - 1213 How Many Tables Today is Ignatius' birthday. He invites ...
- 暑期集训5:并查集 线段树 练习题A: HDU - 1232
2018学校暑期集训第五天--并查集 线段树 练习题A -- HDU - 1232 畅通工程 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅 ...
- UVA1455 - Kingdom(并查集 + 线段树)
UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...
- BZOJ 3910 并查集+线段树合并
思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...
- 【bzoj5133】[CodePlus2017年12月]白金元首与独舞 并查集+矩阵树定理
题目描述 给定一个 $n\times m$ 的方格图,每个格子有 ↑.↓.←.→,表示从该格子能够走到相邻的哪个格子. 有一些格子是空着的,需要填上四者之一,需要满足:最终的方格图中,从任意一个位置出 ...
- P5787 二分图 /【模板】线段树分治(线段树分治、并查集)
关于什么是合理的实现 解析 本题把并查集写在了题面上 然而,我却一直沉浸在一个及其通用的判断二分图的方法中: 一个图是二分图的充要条件是它没有奇环 怎么维护这个玩意?带权并查集! 怎么套线段树分治?可 ...
最新文章
- K8S - Kubernetes简介
- openStack调试
- 重磅!Facebook更新PyTorch 1.1,打算跨GPU分割神经网络
- poj1012(约瑟夫环问题)
- 【高并发】高并发环境下诡异的加锁问题(你加的锁未必安全)
- 2021-春季学习-智能车技术创新与实践-Lesson 1
- COM 组件设计与应用(一)
- 消除ubuntu16.04自带的alt快捷键
- Group Box组合框的简单使用 [大三TJB_708]
- androidmanifest.xml权限中文说明
- 容器编排技术 -- Kubernetes 设计理念
- split出现得问题
- [Java] 蓝桥杯PREV-8 历届试题 买不到的数目
- 第14题 计算机网络故障排除的第二步是,计算机网络故障诊断与排除第1章网络故障和网络诊断测试工具(习题)(ok)...
- java排除文件夹某文件,.gitignore排除文件夹,但包括特定的子文件夹
- 俄罗斯方块-C语言-完整代码
- WMS仓库管理系统出入库流程管理
- vscode 下载加速方法
- PHP创始人:开源与商业软件是竞合关系(转)
- 虚拟摄像头驱动程序彻底分析
热门文章
- JAVA解析Excel工具EasyExcel(alibaba)
- 安装postgres10 后,使用自带的pgAdmin 4 访问数据库,出现The pgAdmin 4 server could not be contacted错误的最完美解决方案,另附安装步骤。
- SharePoint 2016 Search 定制开发简介系列七-Search Database with Security Trimming
- JT/T 808-2013 道路运输车辆卫星定位系统北斗兼容车载终端通讯协议技术规范
- 三地五中心(ldc(逻辑数据中心)单元化)和容灾
- 移动开发平台WorkPlus | 快速实现企业移动应用集成化
- linux ftp pure,linux下安装FTP(pure-ftpd)
- vue+file-saver+xlsx 封装导出Excel表格方法
- 刚申请的博客,就发一个老师让做的“一分钟打动面试官”作业做为纪念吧!!!...
- Pyrhon pyqt5 视频转字符画