kuangbin带我飞QAQ 最短路
1. poj 1502 Mathches Game
裸最短路
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h> #define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = ;
const int maxn = ; struct edge {
int to, next, val;
}e[maxn*maxn]; int dis[maxn], linjie[maxn];
bool vis[maxn];
int N, cnt, ans; void addedge( int x, int y, int val )
{
e[cnt].to = y; e[cnt].next = linjie[x]; e[cnt].val = val; linjie[x] = cnt++; } void init()
{
cnt = ans = ;
memset( linjie, -, sizeof(linjie) );
memset( dis, 0x3f, sizeof(dis) );
memset( vis, , sizeof(vis) );
} void read()
{
init();
string str;
int tmp = ; for ( int i = ; i < N; i++ )
{
for ( int j = ; j < tmp; j++ )
{
int val = ;
cin >> str; if ( str == "x" )
continue;
int len = str.length(); int x = ;
for ( int k = len - ; k >= ; k-- )
{
val += (str[k]-'')*x;
x *= ;
}
addedge( i, j, val );
addedge( j, i, val );
}
tmp++;
}
} void dijkstra()
{
dis[] = ; for ( int i = ; i < N; i++ )
{
int mindis = inf, mark = -;
for ( int j = ; j < N; j++ )
if ( !vis[j] && dis[j] < mindis )
{
mark = j;
mindis = dis[j];
} vis[mark] = true; for ( int j = linjie[mark]; j+; j = e[j].next )
if (!vis[e[j].to])
{
int v = e[j].to, val = e[j].val;
dis[v] = Min(dis[v], dis[mark]+val);
}
}
} int main()
{
cin >> N; read();
dijkstra(); for ( int i = ; i < N; i++ )
ans = Max( ans, dis[i] ); cout << ans << endl;
return ;
}
2. poj 3660 cow contest
floyd 求传递闭包
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h> #define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = ;
const int maxn = ; bool mmap[maxn][maxn];
int ojbk[maxn];
int N, M; void floyd()
{
for ( int k = ; k <= N; k++ )
for ( int i = ; i <= N; i++ )
for ( int j = ; j <= N; j++ )
{
mmap[i][j] = (mmap[i][j] || (mmap[i][k] && mmap[k][j]));
}
} int main()
{
cin >> N >> M; int x, y;
for ( int i = ; i <= M; i++ )
{
scanf("%d %d", &x, &y);
mmap[x][y] = ;
} floyd(); int ans = ;
for ( int i = ; i <= N; i++ )
for ( int j = ; j <= N; j++ )
if ( mmap[i][j] )
{
ojbk[i]++;
ojbk[j]++;
} for ( int i = ; i <= N; i++ )
if ( ojbk[i] == N- )
ans++;
cout << ans << endl; return ;
}
3. poj 1511 Invitation Cards
双向最短路,正着求一次,边取反再求一次
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h> #define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = ;
const int maxn = 1e6+; int num[*maxn];
int linjie[maxn];
int dis[maxn];
bool vis[maxn];
int P, Q, cnt;
long long ans; struct edge {
int to, next, val ;
}e[maxn]; struct cmp {
bool operator() ( const int a, const int b )
{ return dis[a]>dis[b]; }
}; void addedge( int u, int v, int val )
{ e[cnt].to = v; e[cnt].next = linjie[u]; e[cnt].val = val; linjie[u] = cnt++; } void init()
{
cnt = ; ans = ;
memset( linjie, -, sizeof(linjie) );
} void dijkstra()
{
memset( dis, 0x3f, sizeof(dis) );
memset( vis, , sizeof(vis) ); priority_queue<int, vector<int>, cmp> q;
dis[] = ;
q.push(); while (!q.empty())
{
int run = q.top(); q.pop();
int mindis = dis[run]; vis[run] = true; for ( int i = linjie[run]; i+; i = e[i].next )
if ( !vis[e[i].to] && dis[e[i].to] > mindis + e[i].val )
{
dis[e[i].to] = mindis + e[i].val;
q.push(e[i].to);
}
}
for ( int i = ; i <= P; i++ )
ans += (long long)dis[i];
} int main()
{
int n;
cin >> n; while (n--)
{
init();
scanf( "%d %d", &P, &Q ); int j = ;
for ( int i = ; i <= Q; i++ )
{
scanf( "%d %d %d", &num[j], &num[j+], &num[j+] );
addedge( num[j], num[j+], num[j+] );
j += ;
}
dijkstra(); //重新建边///
memset( linjie, -, sizeof(linjie) );
cnt = ; j = ;
for ( int i = ; i <= Q; i++ )
{
addedge( num[j+], num[j], num[j+] );
j += ;
} dijkstra(); printf( "%lld\n", ans );
} return ;
}
4.poj 3159 Candies
dijsktra+优先队列优化+差分约束
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <vector>
#define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = + ;
const int maxn = + ; int linjie[maxn];
int dis[maxn];
bool vis[maxn];
int P, Q, cnt; struct qnode
{
int v;
int c;
qnode(int _v=,int _c=):v(_v),c(_c){}
bool operator <(const qnode &r)const
{
return c>r.c;
}
}; struct edge {
int to, next, val ;
}e[maxk]; void addedge( int u, int v, int val )
{ e[cnt].to = v; e[cnt].next = linjie[u]; e[cnt].val = val; linjie[u] = cnt++; } void init()
{
cnt = ;
memset( linjie, -, sizeof(linjie) );
} void dijkstra()
{
memset( dis, 0x3f, sizeof(dis) );
memset( vis, , sizeof(vis) ); priority_queue<qnode> q;
while(!q.empty()) q.pop();
dis[] = ;
q.push(qnode(,)); qnode tmp; while (!q.empty())
{
tmp = q.top(); q.pop();
int run = tmp.v;
int mindis = dis[run]; vis[run] = true; for ( int i = linjie[run]; i+; i = e[i].next )
if ( !vis[e[i].to] && dis[e[i].to] > mindis + e[i].val )
{
int v = e[i].to;
dis[v] = mindis + e[i].val;
q.push(qnode(v, dis[v]));
}
}
} int main()
{
init();
scanf( "%d%d", &P, &Q ); int x, y, z;
for ( int i = ; i <= Q; i++ )
{
scanf( "%d%d%d", &x, &y, &z );
addedge(x,y,z);
} dijkstra(); printf( "%d\n", dis[P] ); return ;
}
5. poj 3169 Layout
spfa+负环+差分约束
最经典的差分约束,因为求的是dis[N]-dis[1]的最大值 ,即dis[N]-dis[1] <= x,所以用最短路。用spfa判断若有负环,说明最短路无限小,所以无解;若dis[N] = inf,说明最短路可以无限大,
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h> #define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = 2e4+;
const int maxn = ; int N, Ml, Md, cnt;
int linjie[maxn], in[maxn];
bool vis[maxn];
long long dis[maxn]; struct edge {
int to, next, val;
}e[maxk]; void addedge( int u, int v, int val )
{
e[cnt].to = v;
e[cnt].next = linjie[u];
e[cnt].val = val;
linjie[u] = cnt++;
} void init()
{
cnt = ;
memset( linjie, -, sizeof(linjie) );
} long long spfa()
{
memset( dis, 0x3f, sizeof(dis) ); queue<int> q;
q.push(); dis[] = ; while ( !q.empty() )
{
int run = q.front(); q.pop();
vis[run] = false; for ( int i = linjie[run]; i+; i = e[i].next )
{
int v = e[i].to, cost = e[i].val;
if ( dis[v] > dis[run] + cost )
{
dis[v] = dis[run] + cost;
if (!vis[v])
{
in[v]++;
if ( in[v] > N ) return -; vis[v] = true;
q.push(v);
}
}
}
} if ( dis[N] == INF ) return -;
else
return dis[N];
} int main()
{
init();
cin >> N >> Ml >> Md; //差分约束条件建边
int a, b, z;
for ( int i = ; i <= Ml; i++ )
{ scanf("%d%d%d", &a, &b, &z); addedge(a,b,z); }
for ( int i = ; i <= Md; i++ )
{ scanf("%d%d%d", &a, &b, &z); addedge(b,a,-z); } printf( "%lld\n", spfa() );
return ;
}
6. hdu3416 Marriage Match IV
dijkstra+最大流dinic当前弧优化
hdu的题好难...这题最不一样的是求一共有多少条最短路(路径不可以重复),一个暴力的想法就是求一条最短路再删去该路的所有边,再求最短路,再删边,直到求得最短路长度大于第一次求得的长度为止,不过用脚趾头想都知道数据肯定会卡你的。
其实会发现如果抛弃最短路来看,这道题很像最大流,就是所有边权为1求最大流的题目,不过现在加了约束条件必须在最短路上取最大流。所以我们可以求出所有的最短路径的边并重新建一个边权为1的图,在其上做最大流就可以了,那么怎么求所有最短路径呢?
有个方法是从终点dijkstra一下再从起点dijkstra下(注意要建立反向边图),假设dis1[u]表示start-u之间最短距离,dis2[v]表示v-end之间最短距离,那么只要dis1[u]+dis2[v]+dis[u][v] == 最短路长度,就代表这条边是可以要的
#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <math.h> #define SIGMA_SIZE 26
#pragma warning ( disable : 4996 ) using namespace std;
typedef long long LL; inline LL LMax(LL a,LL b) { return a>b?a:b; }
inline LL LMin(LL a,LL b) { return a>b?b:a; }
inline int Max(int a,int b) { return a>b?a:b; }
inline int Min(int a,int b) { return a>b?b:a; }
inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = ;
const int maxk = 1e5+;
const int maxn = ; int N, M, cnt;
int st, ed;
int num[maxk*];
int disst[maxn], dised[maxn], cur[maxn];
int linjie1[maxn], linjie2[maxn];
bool vis[maxn]; struct node {
int to, next, val;
}e1[maxk], e2[maxk]; void addedge1( int u, int v, int val )
{ e1[cnt].to = v; e1[cnt].val = val; e1[cnt].next = linjie1[u]; linjie1[u] = cnt++; }
void addedge2( int u, int v, int val )
{ e2[cnt].to = v; e2[cnt].val = val; e2[cnt].next = linjie2[u]; linjie2[u] = cnt++; } void init()
{
cnt = ;
memset( linjie1, -, sizeof(linjie1) );
memset( linjie2, -, sizeof(linjie2) );
} void dijkstra( int x )
{
memset( vis, , sizeof(vis) );
memset( disst, 0x3f, sizeof(disst) );
disst[x] = ; for ( int k = ; k <= N; k++ )
{
int mark = -, mindis = inf;
for ( int i = ; i <= N; i++ )
if ( !vis[i] && disst[i] < mindis )
{
mark = i;
mindis = disst[i];
}
vis[mark] = true; for ( int i = linjie1[mark]; i+; i = e1[i].next )
{
int v = e1[i].to, cost = e1[i].val;
if ( !vis[v] && disst[v] > disst[mark] + cost )
disst[v] = disst[mark] + cost;
}
}
} void make_map()
{
cnt = ;
int mindist = disst[ed]; for ( int i = ; i <= N; i++ )
for ( int j = linjie1[i]; j + ; j = e1[j].next )
{
int v = e1[j].to, cost = e1[j].val;
if ( disst[i] + cost + dised[v] == mindist )
addedge2( i, v, );
}
} int bfs()
{
memset( disst, -, sizeof(disst) );
queue<int> q; q.push(st);
disst[st] = ; while( !q.empty() )
{
int run = q.front(); q.pop();
for( int i = linjie2[run]; i+; i = e2[i].next )
{
int v = e2[i].to, flow = e2[i].val;
if( disst[v] < && flow > )
{
disst[v] = disst[run] + ;
q.push(v);
}
}
} if( disst[ed] > )
return ;
else
return ;
} int find( int s, int low )
{
int ff = ;
if( s == ed )
return low;
for( int& i = cur[s]; i+; i = e2[i].next ) //注意int& i = cur[s] 当前弧优化
{
int v = e2[i].to, cap = e2[i].val;
if( cap >
&& disst[v] == disst[s] +
&& (ff = find(v,Min(cap,low))) )
{
e2[i].val -= ff;
//e2[i^1].val += ff;
return ff;
}
}
return ;
} int dinic()
{
int ans = ;
int tans;
while( bfs() )
{
for( int i = ; i <= N; i++ ) //当前弧优化
cur[i] = linjie2[i];
while( tans = find( st, inf ) )
ans += tans;
}
return ans;
} int main()
{
int T; cin >> T;
while (T--)
{
scanf("%d%d", &N, &M); init();
for (int i = , j = ; i <= M; i++)
{
scanf( "%d%d%d", &num[j], &num[j+], &num[j+] );
addedge1(num[j+],num[j],num[j+]);
j += ;
} scanf("%d%d", &st, &ed); dijkstra(ed);
for ( int i = ; i <= N; i++ )
dised[i] = disst[i];
cnt = ;
memset( linjie1, -, sizeof(linjie1) );
for ( int i = , j = ; i <= M; i++ )
{
addedge1( num[j], num[j+], num[j+] );
j += ;
}
dijkstra(st);
make_map(); printf( "%d\n", dinic() );
}
return ;
}
kuangbin带我飞QAQ 最短路的更多相关文章
- kuangbin带我飞QAQ 线段树
1. HDU1166 裸线段树点修改 #include <iostream> #include <string.h> #include <cstdio> #incl ...
- kuangbin带我飞QAQ 并查集
1. POJ 2236 给出N个点,一开始图是空白的,两个操作,一个是增加一个点(给出坐标),一个是查询两个点间是否相通,当两点间的距离小于D或者两点通过其他点间接相连时说这两个点相通.并查集维护,每 ...
- kuangbin带我飞QAQ DLX之一脸懵逼
1. hust 1017 DLX精确覆盖 模板题 勉强写了注释,但还是一脸懵逼,感觉插入方式明显有问题但又不知道哪里不对而且好像能得出正确结果真是奇了怪了 #include <iostream& ...
- kuangbin带你飞 最短路 题解
求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...
- 最短路(代码来源于kuangbin和百度)
最短路 最短路有多种算法,常见的有一下几种:Dijstra.Floyd.Bellman-Ford,其中Dijstra和Bellman-Ford还有优化:Dijstra可以用优先队列(或者堆)优化,Be ...
- cdoj 秋实大哥带我飞 最短路走法 含0权边
//做完这题以后终于理解白书上的边为什么要那样定义了 可以很方便的在o(1) 时间内找到反向边 解法:先跑一边最短路,然后检查最短路上有没有0权边(dfs就好,但是每条边只能走一次,这里就需要用异或找 ...
- [kuangbin带你飞]专题四 最短路练习 POJ 3268 Silver Cow Party
题意: 在一个有向图中求n头牛从自己的起点走到x再从x走回来的最远距离 思路一开始是暴力跑dij…… 讲道理不太可能…… 然后就百度了一下 才知道把矩阵转置的话就只需要求两次x的单源最短路…… /* ...
- [ An Ac a Day ^_^ ] [kuangbin带你飞]专题四 最短路练习 POJ 2387 Til the Cows Come Home
求1到N的最短路 注意有重边 跑一遍dijkstra就行 /* *********************************************** Author :Sun Yuefeng ...
- 【算法系列学习】SPFA邻接表最短路 [kuangbin带你飞]专题四 最短路练习 F - Wormholes
https://vjudge.net/contest/66569#problem/F 题意:判断图中是否存在负权回路 首先,介绍图的邻接表存储方式 数据结构:图的存储结构之邻接表 邻接表建图,类似于头 ...
随机推荐
- 初识OpenCV-Python - 003:Mouse as a paint-brush
此次学习了如何在OpenCV中使用鼠标事件.主要使用cv2.setMouseCallback()函数来调用鼠标事件. 首先,鼠标有如下事件: >>> import cv2>&g ...
- <每日一题>算法题:集合求并集并排序
题目描述 给你两个集合,要求{A} + {B}. 注:同一个集合中不会有两个相同的元素. 输入描述: 每组输入数据分为三行,第一行有两个数字n,m(0 ≤ n,m ≤ 10000),分别表示集合A和集 ...
- Echarts——更改仪表盘方向和颜色
做小项目需要用到仪表盘,官方给出的颜色设置如下: 而我想要如下样式的: 最后,经过一番折腾算是搞成了如下样式效果: 要达到上面效果关键在于设置Echarts的如下两处js代码: 1.大小值要颠倒,因为 ...
- sql 根据列名查所属表名
比如 有一个jueseID字段,想知道这个字段是哪个表里的. 第一步: select * from syscolumns where name = 'jueseID' 第二步: select * fr ...
- art-template官方文档
http://aui.github.io/art-template/zh-cn/docs/
- Java中Arrys数组常用的方法
Arrys常用方法 1.toString() Arrays.toString(arr) //打印数组的内容,观察数组元素的值 2.sort() Arrays.sort(arr); ...
- python requests 高级用法 -- 包括SSL 证书错误的解决方案
Session Objects会话对象 Session对象在请求时允许你坚持一定的参数.此外,还坚持由Session实例的所有请求的cookie. 让我们坚持在请求时使用 s = requests.S ...
- BZOJ2741:[FOTILE模拟赛]L
Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 .. ...
- Bash Specially-crafted Environment Variables Code Injection Vulnerability Analysis
http://www.cnblogs.com/LittleHann/p/3992778.html
- VUX的使用方法(以弹出框为例)
一.安装 cnpm install vux --save cnpm install vux-loader --save-dev 二.配置 const vuxLoader = require('vux- ...