vis

图论算法总结(一)――图的遍历

匿名 (未验证) 提交于 2019-12-03 00:09:02
关于数据结构,主要是有关树和图是最终的难点和痛点,关于算法,记住名字很简单,记住原理要花一点时间,如何内化为自己本身的知识,以及,在脑中有思路,随拿随用,这个需要特定的记忆方式。如果不能即拿即用,并不能说自己了解这个算法。建议大家,以自己的思维为中心,记住该思维的逻辑的同时,也记住该思路的代码,把算法内化为自己的修养。 参考博文:) 按照深度优先方式访问未访问的节点 dfs ( u ){ vis [ u ]= true ; for (从 u 出发能到达的所有顶点 v ) if ( vis [ v ]== false ) dfs ( v ); } dfsTrave ( G ){ for ( G 的所有节点 u ) if ( vis [ u ]== false ) dfs ( u ) } //邻接矩阵 void dfs ( int u ){ vis [ u ]= 1 ; printf ( "%d" , u ); for ( int i = 0 ; i < vertxNum ; i ++) if ( vis [ i ]== 0 && path [ u ][ i ]== 1 ) dfs ( i ); } void dfsTrave (){ for ( int i = 0 ; i < vertxNum ; i ++) if ( vis [ i ]== false ) dfs ( i ); }

【PAT甲级】1034 Head of a Gang (30 分)

匿名 (未验证) 提交于 2019-12-03 00:05:01
题意: 输入两个正整数N和K(<=1000),接下来输入N行数据,每行包括两个人由三个大写字母组成的ID,以及两人通话的时间。输出团伙的个数(相互间通过电话的人数>=3),以及按照字典序输出团伙老大的ID和团伙的人数(团伙中通话时长最长的人视为老大,数据保证一个团伙仅有一名老大)。 代码: #define HAVE_STRUCT_TIMESPEC #include<bits/stdc++.h> using namespace std; string s,s2; int x[1007],y[1007]; vector<pair<int,int> >edge[20007]; bool vis[20007]; int val[20007]; int mx=0; int pos=0; int ans[20007]; int num[20007]; int cnt=0; int c[1007]; bool visedge[1007]; int sum2=0; void dfs(int x){ if(!vis[x]) ++cnt; vis[x]=1; for(auto it:edge[x]){ if(visedge[it.second]) continue; visedge[it.second]=1; if(!vis[it.first]){ ++cnt; vis[it.first]=1; }

最小费用最大流模板

匿名 (未验证) 提交于 2019-12-03 00:05:01
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 #define INF 2147483647 7 #define LL long long 8 using namespace std; 9 queue<int>q; 10 int n,m,m1,t1,m2,t2,num=-1,st,ed; 11 struct node{ 12 int x,y,c,d,next; 13 }G[100000]; 14 int b[100000],head[100000],pre[100000],pos[100000],max_flow[100000]; 15 LL dis[100000]; 16 bool vis[100000]; 17 void ins(int x,int y,int c,int d) 18 { 19 G[++num].x=x;G[num].y=y;G[num].c=c;G[num].d=d;G[num].next=head[x];head[x]=num; 20 G[++num].x=y;G[num].y=x;G[num].c=0;G[num].d=-d;G[num].next=head[y];head[y]=num; 21 } 22

网络流24题の详解

匿名 (未验证) 提交于 2019-12-03 00:02:01
把网络流24题刷完我就算萌新了。 (持续更新直到刷完为止) \(1.\) 洛谷P2756 飞行员配对方案问题 题意:派出最多架的飞机,并且每架飞机上都是一个英国飞行员和外籍飞行员 分析:经典的二分图匹配问题,将英国飞行员当做二分图的左部,外籍飞行员当做二分图的右部。可以用匈牙利算法求解,但这里使用网络流(最大流)。 考虑如何建图: 设立一个源点 \(st\) ,一个汇点 \(ed\) 。 \(I.\) 让源点 \(st\) 向二分图的左部建一条流量为 \(1\) 的边, \(II.\) 让二分图的右部向汇点 \(ed\) 建一条流量为 \(1\) 的边, \(III.\) 如果英国飞行员 \(u\) 可以和外籍飞行员 \(v\) 配合,那么 \(u\) 和 \(v\) 建一条流量为 \(1\) 的边。 最后跑一遍最大流即可得到最大匹配数。 如何输出配对方案: 遍历所有的英国飞行员所连的边,如果此边 \((u,v)\) 流量不是 \(1\) 而是 \(0\) 说明 \((u,v)\) 配对。注意源点向英国飞行员所连的边流量会为0,但此时不应输出。 #include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,

AcWing - 95 - 费解的开关 = bfs

匿名 (未验证) 提交于 2019-12-02 23:57:01
https://www.acwing.com/problem/content/97/ 看了一下感觉可以暴力做,踩了一些坑终于过了。 #include < bits / stdc ++. h > using namespace std ; typedef long long ll ; int cur ; int set_ij ( int u , int i , int j ) { int cur = u ; cur ^= 1 << ( i * 5 + j ); if ( i - 1 >= 0 ) cur ^= 1 << (( i - 1 ) * 5 + j ); if ( j - 1 >= 0 ) cur ^= 1 << ( i * 5 + j - 1 ); if ( i + 1 < 5 ) cur ^= 1 << (( i + 1 ) * 5 + j ); if ( j + 1 < 5 ) cur ^= 1 << ( i * 5 + j + 1 ); return cur ; } char vis [ 1 << 25 ]; int Q [ 1 << 20 ], front , back ; void bfs1 () { vis [ cur ] = 0 ; front = 1 ; back = 0 ; Q [++ back ] = cur ; while ( front <=

【NOIP2017】宝藏(状压DP/爆搜)

匿名 (未验证) 提交于 2019-12-02 23:55:01
问题: 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度。 小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多。 小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某 个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。 在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以 任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路 所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏 屋之间的道路无需再开发。 新开发一条道路的代价是: L×K L代表这条道路的长度,K代表从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的 宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋) 。 请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代 价最小,并输出这个最小值。 解: 细数我做这道题的心历路程 首先我看到n这么小 我就先定义 了 $f[i]$ 表示集合 都遍历的最小花费                $dis[j]$ 表示j的深度 (我开始没看出来要选一棵树,还有深度

洛谷P5022&P5049 旅行(及其数据加强版)

风格不统一 提交于 2019-12-02 23:52:32
旅行(不是加强版) 加强版 加强版数据范围: 我们注意到 也就是说要么是个树,要么是个基环树 60pts 这60分是个树,可以简单的贪心想到每次都走子树中编号最小的那个,并且把1作为根 dfs练手题 还是贴个代码叭 void dfs1(int now,int fa) { if(vis[now])return ; ans1[++t]=now; vis[now]=1; vector<int> qwq;//为了不使存储的点被后面的子树覆盖,所以用vector for(int e=head[now];e;e=ed[e].nxt) { int v=ed[e].to; if(v==fa)continue; qwq.push_back(v); } sort(qwq.begin(),qwq.end());//vector的排序 int qaq=qwq.size(); for(int i=0;i<qaq;i++) dfs1(qwq[i],now); } 100pts 大多数的解法 当m==n时,它是一个基环树(即树上挂着一个环的树) 基环树只要删掉环上的一条边,它就是个树了。所以我们可以枚举删掉哪条边。(需要开个 \(O_2\) ) 由于开 \(O_2\) 会让你的评测记录显得不优雅,我们要考虑考虑怎么不开 \(O_2\) 过掉这道题。 由于我们要删去环上的边,所以要先找个环

sort(桶排序+hash)

匿名 (未验证) 提交于 2019-12-02 23:49:02
题目链接: https://cn.vjudge.net/problem/HDU-1425 注意是多组输入 代码: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<stack> #include<set> #include<vector> #include<cmath> #define Inf 0x3f3f3f3f const int maxn=1e5+5; typedef long long ll; using namespace std; int vis[maxn*10]; int ans[maxn*10]; int main() { int n,m; while(cin>>n>>m) { memset(vis,0,sizeof(vis)); int x; int maxx=-Inf; for(int t=0;t<n;t++) { scanf("%d",&x); maxx=max(maxx,x+500000); vis[x+500000]++; } int cnt=0; int nn=maxx; while(cnt<m) { while(vis[nn]) { vis[nn]--; ans[cnt]=nn-500000; cnt++;

UVa11134传说中的车

匿名 (未验证) 提交于 2019-12-02 23:49:02
3 1 1 3 3 1 1 3 3 2 2 2 2 // UVa 11134 // 问题分解 /* 横与竖互不影响,所以将它们分开进行计算,这样我们将 二维转化成为了一维,然后成为了区间选点类似的问题,贪心法进行求解。 */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 5000 + 5; int X0[maxn], X1[maxn], Y0[maxn], Y1[maxn], rec[maxn], vis[maxn]; int r[maxn], c[maxn]; bool cmp1(int a, int b) { // 关于x的排序 if (X1[a] != X1[b]) return X1[a] < X1[b]; return X0[a] > X0[b]; } bool cmp2(int a, int b) { // 关于y的排序 if (Y1[a] != Y1[b]) return Y1[a] < Y1[b]; return Y0[a] > Y0[b]; } int main() { int n; while (scanf("%d", &n) == 1 && n) { for (int i = 0; i < n; ++i) rec[i

【广搜】Keyboarding

匿名 (未验证) 提交于 2019-12-02 23:49:02
题目描述 给定一个r行c列的在电视上的“虚拟键盘”,通过“上,下,左,右,选择”共5个控制键,你可以移动电视屏幕上的光标来打印文本。一开始,光标在键盘的左上角,每次按方向键,光标总是跳到下一个在该方向上与当前位置不同的字符,若不存在则不移动。每次按选择键,则将光标所在位置的字符打印出来。 现在求打印给定文本(要在结尾打印换行符)的最少按键次数。 输入 第一行输入 r,c。 接下来给出一个 r×c的键盘,包括大写字母,数字,横线以及星号(星号代表 Enter 换行)。 最后一行是要打印的文本串 S,S 的长度不超过 10000。 输出 输出打印文本(包括结尾换行符)的最少按键次数。保证一定有解。 样例输入 2 19 ABCDEFGHIJKLMNOPQZY X*****************Y AZAZ 样例输出 19 提示 对于100%的数据,1≤r,c≤50,S的长度不超过10000。 【题解】 这个题目需要大家耐心处理细节,预处理所有点的四个方向能到达的地方。 然后用BFS搜索,注意搜索的顺序,已经利用好vis标记数组来记录。 1 #pragma GCC optimize("Ofast") //编译环境优化 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N = 52 ; 5 const int M =