海亮第二天,想着说预习一下的,可是昨天10h+都没有把那六道题打完,就打了四道,上午就讲完课了,还是延续昨天的博客,今天接着总结。。

欧拉路

开头就是特别经典的七桥问题,讲欧拉路一定会讲到的问题,也就是从小最熟悉的一笔画问题。
欧拉路:如果一个图存在一笔画,则一笔画的路径就是欧拉路。
欧拉回路:如果一个图存在一笔画而且最后又回到了起点(不重复走过所有的路径),则其路径就是欧拉回路。
存在欧拉路的条件:图是连通的,有且只有2 个奇点。
存在欧拉回路的条件:图是连通的,有0 个奇点。
延伸:
哈密尔顿环: 指不重复走过所有点并且最后还能回到起点的回路。

Hierholzer

(具体怎么念,还没不是很清楚,好像是海尔后泽…(xia shou de bie xin ))
伪代码
(因为不会很好的总结,就直接上大神的PPT>_<)

步骤:
1 判断奇点数。奇点数若为0则任意指定起点,奇点数若为2则指定起点为奇点。
2 开始递归函数Hierholzer(x):循环寻找与x相连的边(x,u):删除(x,u)删除(u,x)Hierholzer(u);将x插入答案队列之中具体代码:
void euler(int u)
{for(int i=begin;i<=end;i++)if(a[u][i]>=1)\{a[u][i]--;a[i][u]--;euler(i);}   ans[++anssize]=u;
}

放一个欧拉回路的题:POJ - 1386
是有意思的个板子 题,,,

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
int fa[26],r[26],c[26],v[26];
char a[1200];
//并查集
int find(int n) {return n==fa[n]?n:fa[n]=find(fa[n]);}
void merge(int a,int b) {a=find(a);b=find(b);fa[a]=b;}
int main()
{int n;cin>>n;while(n--){int m;cin>>m;memset(v,0,sizeof(v));memset(c,0,sizeof(c));memset(r,0,sizeof(r));for(int i=0;i<26;i++) fa[i]=i;for(int i=0;i<m;i++){cin>>a;int x=a[0]-'a';int y=a[strlen(a)-1]-'a';//只用记录这串字母的首尾即可,可以简化操作并降低复杂度merge(x,y);v[x]=v[y]=true;c[x]++; r[y]++;//跑欧拉路}int q1=0,q2=0,q3=0,q4=0;for(int i=0;i<26;i++)if(v[i]){q1++;if(fa[i]==i)q2++;if(c[i]==r[i])q3++;if(abs(r[i]-c[i])==1)q4++;}if(q2==1&&(q1==q3)||(q4==2&&q3+q4==q1))//判断是不是环或是可以连接cout<<"Ordering is possible."<<endl;else cout<<"The door cannot be opened."<<endl;}return 0;
}

在放个有意思的题…
太鼓达人 HYSBZ - 3033
这道题好有意思好有意思好有意思 ,
大佬给的题解就一句话:欧拉回路
本蒟蒻的题解就算了吧,(一定会补齐的,要相信我!!!)

#include<iostream>
using namespace std;
int ans,kk,n,t,d[1000000];
bool v[100000];
bool euler(int x,int y)
{if(v[x]) return 0;d[y]=x&1;v[x]=true;if(y==kk) return 1;if(euler((x<<1)&t,y+1)) return 1;if(euler((x<<1|1)&t,y+1)) return 1;v[x]=false;
}
int main()
{cin>>n;kk=1<<n;cout<<kk<<' ';t=kk-1;euler(kk-2,1);for(int i=1;i<=kk;i++)cout<<d[i];return 0;
}
//是不是有点像hzwer的代码,,,原因就不说了,跟没有题解一个原因,,,

(早知道不会就不放了,,,>_<)

拓扑排序

topu板子

void topu()
{int i,j,now;queue<int>q;for(int i=1;i<=n;i++)if(!ind[i]) q.push(i);while(!q.empty()){now=q.front;q.pop();ans[++cnt]=now;for(int i=last[now];i;i=e[i].next){ind[e[i].ver]--;if(!ind[e[i].ver])q.push(e[i].ver);}if(cnt!=n) puts("-1");else for(int i=1;i<=n;i++)
//      cout<<ans[i]<<' ';printf("%d",ans[i]);
//      一个极好的建议:别用cout,在1e6之后就死了,曾经本蒟蒻就是没有这个常识,在一道题中整整TLE了两个小时,还TLE了整整10遍,,一把辛酸泪}
}

放一个也很有意思的题,,,(不是很想这么说了>_>)
CodeForces - 516B
一道很有意思的topu+搜索的题,这个应该算有意思了,

#include<bits/stdc++.h>
#define ll long long
#define sea 0x3fffffff
#define mp make_pair
using namespace std;
int n,m;
int d[2500][2500];
int dx[]={0,1,-1,0,0};
int dy[]={0,0,0,-1,1};
char od[2200][22000]; //读入时的数组
queue<pair<int,int> >Q;
int main()
{cin>>n>>m;for(int i=1;i<=n;i++)scanf("%s",od[i]+1);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(od[i][j]=='*') d[i][j]=0;else for(int k=1;k<=4;k++){int xx=dx[k]+i,yy=dy[k]+j;if(xx<1||xx>n||yy<1||yy>m||od[xx][yy]=='*') continue;d[i][j]++;}}//以上是读入并预处理//下面开始大暴搜:for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(d[i][j]==1) Q.push(mp(i,j));while(!Q.empty()){int x=Q.front().first,y=Q.front().second; Q.pop();if(d[x][y]==0) continue;for(int i=1;i<=4;i++){int xx=dx[i]+x,yy=dy[i]+y;if(xx<1||xx>n||yy<1||yy>m||od[xx][yy]!='.') continue;d[x][y]=d[xx][yy]=0;if(i==1) od[x][y]='^',od[xx][yy]='v';if(i==2) od[x][y]='v',od[xx][yy]='^';if(i==3) od[x][y]='>',od[xx][yy]='<';if(i==4) od[x][y]='<',od[xx][yy]='>';for(int j=1;j<=4;j++){int xxx=dx[j]+xx,yyy=dy[j]+yy;if(xxx<1||xxx>n||yyy<1||yyy>m||od[xxx][yyy]!='.') continue;if(--d[xxx][yyy]==1) Q.push(mp(xxx,yyy));}}}//要是会搜索就特别简单了,要是不会的话就不是会很容易了O.Ofor(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(od[i][j]=='.') {cout<<"Not unique"<<endl; return 0;}for(int i=1;i<=n;i++) cout<<od[i]+1<<endl;return 0;
}

差分约束

(粘概念):通俗一点地说,差分约束系统就是一些不等式的组,而我们的目标是通过给定的约束不等式组求出最大值或者最小值或者差分约束系统是否有解。
之所以差分约束系统可以通过图论的最短路来解,是因为 x j ± x_j\pm xj​± x i x_i xi​ < = b k <= bk <=bk类似最短路中的三角不等式 d [ v ] < = d [ u ] + w [ u ] [ v ] d[v]<=d[u]+w[u][v] d[v]<=d[u]+w[u][v],
即 d [ v ] − d [ u ] < = w [ u ] [ v ] d[v]-d[u]<=w[u][v] d[v]−d[u]<=w[u][v]。而求取最大值的过程类似于最短路算法中的松弛过程。
三角不等式:
B − A < = c B-A<= c B−A<=c
C − B < = a C-B<=a C−B<=a
C − A < = b C-A<=b C−A<=b
如果要求 C − A C-A C−A的最大值,可以知道为 m i n ( b , a + c ) min(b, a + c) min(b,a+c),而这正对应了C到A的最短路。
这个知识点需要用题巩固,毕竟这只是一种思想。
POJ - 3169

#include<bits/stdc++.h>
#define sea 11000000
#define maxn 85251
using namespace std;
int tot,n,ml,md;
int d[110000],sum[110000];
bool v[110000];
struct see {int next,last,ver,edge;}e[110000];
void add(int x,int y,int z)
{e[++tot].ver=y;e[tot].edge=z;e[tot].next=e[x].last;e[x].last=tot;}
int spfa()
{queue<int>Q;for(int i=2;i<=maxn;i++)d[i]=sea;sum[1]++; d[1]=0; v[1]=1; Q.push(1); while(!Q.empty()){int x=Q.front(); Q.pop(); v[x]=0;for(int i=e[x].last;i;i=e[i].next){int y=e[i].ver,z=e[i].edge;if(d[y]>d[x]+z){d[y]=d[x]+z;if(!v[y]){v[y]=1;Q.push(y);sum[y]++;if(sum[y]>n) return 1;}}}}return 0;
}
int main()
{cin>>n>>ml>>md;while(ml--){int x,y,z; cin>>x>>y>>z;add(x,y,z);}while(md--){int x,y,z; cin>>x>>y>>z;add(y,x,-z);}//差分约束就是在建图时的一种思想for(int i=1;i<n;i++)add(i+1,i,0);if(spfa()) cout<<-1<<endl;//跑个裸的spfa即可else if(d[n]==sea) cout<<-2<<endl;else cout<<d[n]<<endl;return 0;
}

放一道有意思 的题:
POJ - 2983
dist[A]-dist[B]>=X,表示A在B北边至少X光年位置。变形为:dist[B]<=dist[A]-X;所以A指向B有条权值为-X的边。对于A-B = X,建两条边dist[B]<=dist[A]-X,dist[A]<=dist[B]+X。
SPFA存在负权环则说明不符合实际情况。

#include<bits/stdc++.h>
#define maxn 95276
#define sea 100000
using namespace std;
int tot,n,m,d[1010],v[1010],sum[1010],last[1010];
struct see{int ver,edge,next;}e[1000000];
void add(int x,int y,int z)
{ e[++tot].ver=y;e[tot].edge=z;e[tot].next=last[x];last[x]=tot;}
int spfa()
{queue<int>Q;memset(sum,0,sizeof(sum));memset(v,0,sizeof(v));memset(d,0x3f,sizeof(d));d[0]=0; v[0]=1; Q.push(0);sum[0]=1; while(!Q.empty()){int x=Q.front(); Q.pop(); v[x]=0; sum[x]++;if(sum[x]>n) return 0;for(int i=last[x];i;i=e[i].next){int y=e[i].ver,z=e[i].edge;if(d[y]>d[x]+z){d[y]=d[x]+z;if(!v[y]) v[y]=1,Q.push(y);}}}return 1;
}
int main()
{while(scanf("%d%d",&n,&m)!=EOF){memset(last,0,sizeof(last));char c[2];int x,y,z;        while(m--){scanf("%s",c);if(c[0]=='P'){cin>>x>>y>>z;add(y,x,z),add(x,y,-z);}else{cin>>x>>y; add(x,y,-1);}}for(int i=1;i<=n;i++) add(0,i,0);//与超级汇点类似的一个大点if(spfa())cout<<"Reliable"<<endl;else cout<<"Unreliable"<<endl;}return 0;
}

再放一道,,的题(不说了),
HDU - 3440
令d[i]表示第i栋房子与第一栋房子之间的最大距离,那么我们要求的就是的d[n]。首先每栋房子之间的相对位置已经确定且不能在同一位置,那么d[i+1] > d[i],即d[i+1]- d[i]>=1,即d[i]-d[i+1] <=-1。
还有一个条件是相邻两个要跳跃的距离不可以大于D,可以写出另一个方程。
有一点小问题就是建边的方向和跳跃的方向不同,我们要保证是向一个方向建图的。
若从左到右建边,如果1在n的左面就从1到n跑SPFA,反之则从n到1跑最短路了。

#include<bits/stdc++.h>
using namespace std;
bool v[11000];
int tot,n,m,T,d[11000],last[11000],sum[11000];
struct see{int num,v;}g[1000000];
bool compare(see a,see b) {return a.v<b.v;}
struct watch{int ver,edge,next;}e[1000000];
void add(int x,int y,int z)
{ e[++tot].ver=y;e[tot].edge=z;e[tot].next=last[x];last[x]=tot;}
int spfa(int u,int s)
{queue<int>Q;memset(sum,0,sizeof(sum));memset(v,0,sizeof(v));memset(d,0x3f,sizeof(d));d[u]=0; v[u]=1; Q.push(u);while(!Q.empty()){int x=Q.front(); Q.pop(); v[x]=0; sum[x]++;if(sum[x]>n) return -1;for(int i=last[x];i;i=e[i].next){int y=e[i].ver,z=e[i].edge;if(d[y]>d[x]+z){d[y]=d[x]+z;if(!v[y]) v[y]=1,Q.push(y);}}}return d[s];
}
int main()
{cin>>T;for(int t=1;t<=T;t++){ memset(last,0,sizeof(last));tot=0;cin>>n>>m; for(int i=1;i<=n;i++){cin>>g[i].v;g[i].num=i;if(i!=n) add(i+1,i,-1);}sort(g+1,g+n+1,compare);for(int i=1;i<n;i++){int x=g[i].num,y=g[i+1].num;if(x>y) swap(x,y);add(x,y,m);}int x=g[1].num,y=g[n].num;if(x>y) swap(x,y);cout<<"Case "<<t<<": "<<spfa(x,y)<<endl;} return 0;
}

今天就总结到这里吧,这个专题也不是算太难,只要好好学学就能大概读懂思路,然后就是刷题,其实最好的老师就是代码。(本人不对自己的话负法律责认>v<).

海亮Day2:差分约束、拓扑排序、欧拉路相关推荐

  1. Awcing1192. 奖金(差分约束/拓扑排序)

    题目 由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金. 公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少. 于是 ...

  2. week8作业/差分约束/拓扑排序/强连通图

    文章目录 A,D-区间选点II 题目: Input: Output: Sample Input: Sample Output: 题目分析: 代码: B-猫猫向前冲 题目: Input: Output: ...

  3. 【图论专题】拓扑排序

    拓扑排序 给定一张有向无环图,若一个序列A满足图中的任意一条边(x,y)x都在y的前面呢么序列A就是图的拓扑排序 实际上拓扑排序就是满足所有的边x指向y,x一定在y的前面.这样按照拓扑排序递推,就可以 ...

  4. D2欧拉路,拓扑排序,和差分约束

    第一题:太鼓达人:BZOJ3033 题意:给出k,求一个最长的M位01串,使其从每一个位置向后走k个得到 的M个k位01串互不相同(最后一个和第一个相邻,即是一个环).输出 字典序最小的答案. 2 ≤ ...

  5. HDU1811 Rank of Tetris 拓扑排序+并查集 OR 差分约束最短路+并查集

    题目链接 题意:就是给你一堆关系,看能不能排出个确定的顺序 做法: 1. 拓扑排序+并查集 应该很容易想到的一种思路,大于小于建立单向边.对于相等的呢,就把他们缩成一个点.就用并查集缩成一个点就行了 ...

  6. Week8 :差分约束,拓扑排序和kahn,强连通图和kosaraju

    文章目录 差分约束 题目-区间选点II 输入输出 解题 代码 拓扑序列-kahn 题目-猫猫向前冲 输入输出 解题 代码 强连通图SCC-kosaraju 题目-班长竞选 输入输出 解题 代码 差分约 ...

  7. 1192 奖金(拓扑排序求解差分约束问题)

    1. 问题描述: 由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金.公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多 ...

  8. WEEK(8)作业——差分约束、拓扑排序(Kahn算法)、SCC(强连通分量)、DFS序、Kosaraju算法

    A-区间选点Ⅱ 题目描述 给定一个数轴上的 n 个区间,要求在数轴上选取最少的点使得第 i 个区间 [ai, bi] 里至少有 ci 个点 使用差分约束系统的解法解决这道题 Input 输入第一行一个 ...

  9. 程序设计——第八周(差分约束:选数问题;拓扑排序:求比赛名次;scc:选班长)

    A.差分选数 题目描述 给定一个数轴上的 n 个区间,要求在数轴上选取最少的点使得第 i 个区间 [ai, bi] 里至少有 ci 个点 使用差分约束系统的解法解决这道题 使用差分约束系统的解法解决这 ...

最新文章

  1. linux c icmp协议 判断主机存活
  2. 问题排查:单表3000笔数据查询竟然要2秒?
  3. 毕业了,在Python中使用 OpenCV 和K-Means 聚类对毕业照进行图像分割
  4. 主播靠颜值还是???!!!!!
  5. Flash 生命终止,HTML5能否完美替代?
  6. arcgis批量处理nc文件_法律行业python教程——利用python批量处理文件之批量重命名...
  7. 登录页面(通过数据库查询密码是否正确)
  8. 求 LCA 的三种方法
  9. 1.14_radix_sort_基数排序
  10. c语言kmeans算法具体步骤,k-均值聚类算法c语言版
  11. Linux添加/删除用户和用户组(linux中,添加cvs用户,实质就是添加linux用户。)
  12. MySQL 分区表——《高性能MySQL》
  13. Redis源码分析之内存检测memtest
  14. 东芝机械手tspc安装_日本东芝工四轴机械手THL800
  15. java调用平方函数_java中的数学计算函数的总结
  16. 乐队的夏天大结局!用Python分析投票数据,选出真正的乐队TOP 5
  17. 怎么修改Word每行文字间距
  18. 商城购物APP——YiGo
  19. 将iPhone投影到Mac上
  20. Deep Graph Kernels

热门文章

  1. 《青木瓜之味》配色分享
  2. Fiddler + 海马模拟器转包教程
  3. Kali网卡设置comfast cf-812AC(Realtek 8812BU芯片)
  4. 浪潮小机装oracle数据库,浪潮ERP-PS V10.2安装手册.doc
  5. 学生计算机培训策划培训流程,培训策划书
  6. Mycat高级进阶---读写分离
  7. 【RoboMaster】从零开始控制RM电机(2)-CAN通信原理及电调通信协议
  8. ftp服务器响应很慢,有果必有因:FTP传输速率慢和TCP窗口、网络时延的因果案例...
  9. 云计算敏捷团队的 10 个最佳实践工具
  10. 公司注册资金认缴和实缴有什么区别