最短路建图

BZOJ-4152

分析

%大佬博客
注意:本题卡spfa;

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <queue> 
#include <map> 
#include <set> 
#include <bitset>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
template<typename xxx>inline void read(xxx &x) {
	x = 0;int f = 1;char c = getchar();
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') f = -1,c = getchar();
	for(;isdigit(c);c = getchar()) x = (x << 3) + (x << 1) + (c ^ '0');
	x *= f;  
}
template<typename xxx>inline void print(xxx x) {
	if(x < 0) {
		putchar('-');
		x = -x;
	}
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int maxn = 200010;
const int mod = 1e9 + 7;
const int inf = 0x7f7f7f7f;
struct node {
	int xi,yi,id;
}g[maxn];
inline bool gmpx(node a,node b) {
	if(a.xi == b.xi) return a.yi < b.yi;
	else return a.xi < b.xi;
}
inline bool gmpy(node a,node b) {
	if(a.yi == b.yi) return a.xi < b.xi;
	else return a.yi < b.yi;
}
struct edge {
	int to,last;
	ll val;
}e[maxn<<2];
int head[maxn<<2],tot;
inline void add(int from,int to,ll val) {
	++tot;
	e[tot].to = to;
	e[tot].val = val;
	e[tot].last = head[from];
	head[from] = tot;
} 
int n;
ll dis[maxn];
int vis[maxn];
queue<int>q;
inline void spfa() {
	for(rint i = 0;i <= n; ++i) dis[i] = 1e16;
	q.push(1);dis[1] = 0;
	while(q.size()) {
		int x = q.front();q.pop();vis[x] = 0;
		for(rint i = head[x];i;i = e[i].last) {
			if(dis[e[i].to] > dis[x] + e[i].val) {
				dis[e[i].to] = dis[x] + e[i].val;
				if(!vis[e[i].to]) {
					vis[e[i].to] = 1;
					q.push(e[i].to);
				}
			}
		}
	}
	return ;
}
int main() {
	read(n);
	for(rint i = 1;i <= n; ++i) {
		read(g[i].xi);
		read(g[i].yi);
		g[i].id = i;
	}
	stable_sort(g + 1,g + n + 1,gmpx);
	for(rint i = 1;i < n; ++i) {
		int disx = g[i + 1].xi - g[i].xi;
		int disy = g[i + 1].yi - g[i].yi;
		if(disx < 0) disx = -disx;
		if(disy < 0) disy = -disy;
		if(disx <= disy) {
			add(g[i].id,g[i + 1].id,disx);
			add(g[i + 1].id,g[i].id,disx);
//			cout<<i<<" "<<i + 1<<" "<<disx<<endl;
		}
	}
	stable_sort(g + 1,g + n + 1,gmpy);
	for(rint i = 1;i < n; ++i) {
		int disx = g[i + 1].xi - g[i].xi;
		int disy = g[i + 1].yi - g[i].yi;
		if(disx < 0) disx = -disx;
		if(disy < 0) disy = -disy;
		if(disx >= disy) {
			add(g[i].id,g[i + 1].id,disy);
			add(g[i + 1].id,g[i].id,disy);
//			cout<<i<<" "<<i + 1<<" "<<disy<<endl;
		}
	}
	spfa();
	print(dis[n]);
}
/*
*/

HDU-4725

分析

每层增设两个虚点,层内点只能通过一个走向相邻层,相邻层点只能走另一点到该层。两点与本层的点连权为0的边,向外连长为c的边。本题理论上有相邻层不连通情况,但是数据没有...
注意:数组要开大,否则会wa一上午

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <queue> 
#include <map> 
#include <set> 
#include <bitset>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
template<typename xxx>inline void read(xxx &x) {
	x = 0;int f = 1;char c = getchar();
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') f = -1,c = getchar();
	for(;isdigit(c);c = getchar()) x = (x << 3) + (x << 1) + (c ^ '0');
	x *= f;  
}
template<typename xxx>inline void print(xxx x) {
	if(x < 0) {
		putchar('-');
		x = -x;
	}
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int maxn = 1000010;
const int mod = 1e9 + 7;
const int inf = 0x7f7f7f7f;
struct edge {
	int to,last;
	int val;
}e[maxn];
int head[maxn],tot;
inline void add(int from,int to,int val) {
	++tot;
	e[tot].to = to;
	e[tot].val = val;
	e[tot].last = head[from];
	head[from] = tot;
} 
int n,m,C;
int dis[maxn];
int vis[maxn];
int num[maxn/10];
priority_queue< pair<ll,int> >q;
inline void spfa() {
	memset(dis,0x7f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	q.push(make_pair(0,1));dis[1] = 0;
	while(q.size()) {
		int x = q.top().second;q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		for(rint i = head[x];i;i = e[i].last) {
			if(vis[e[i].to]) continue;
			if(dis[e[i].to] > dis[x] + e[i].val) {
				dis[e[i].to] = dis[x] + e[i].val;
				q.push(make_pair(-dis[e[i].to],e[i].to)); 
			}
		}
	}
	return ;
}
int main() {
	int t;read(t);
	for(rint o = 1;o <= t; ++o) {
		tot = 0;
		memset(num,0,sizeof(num));
		memset(head,0,sizeof(head));
 		read(n);read(m);read(C);
		for(rint i = 1;i <= n; ++i) {
			int tp ;
			read(tp);
			add(i,n + tp,0);
			add((n << 1) + tp,i,0);
			++num[tp];
		}
		for(rint i = 1;i <= m; ++i) {
			int a,b,c;
			read(a);read(b);read(c);
			add(a,b,c);
			add(b,a,c);
		}
		for(rint i = 2;i <= n; ++i) {
			if(num[i - 1] && num[i]) {
				add(n + i,(n << 1) + i - 1,C);
				add(n + i - 1,(n << 1) + i,C);
			}
		}		
		spfa();
		printf("Case #%d: ",o);
		if(dis[n] == 0x7f7f7f7f) print(-1);
		else print(dis[n]);
		putchar('\n'); 
	} 
}
/*
*/

[BZOJ-2259]

分析

本题亦可以dp做
我们考虑把序列的每个下标看做一种状态,dis[i]表示把i之前的点恰好完全处理所需的最小花费,明显dis[n + 1]是答案。考虑暴力建边,如果i + a[i] + 1 <= n + 1(即i + a[i] <= n),那么由题目可知状态i到状态i + a[i]花费为0,否则i到i + a[i]的花费为i + a[i] - n(因为ai要减去这么多)。其他的边暴力建会导致\(O(n^2)\),我们则可以考虑让每个点与它前后向邻点建权为1的边,每个点刚好有加或减两种选择。特殊:1前面没有点不需建向前的边,1后面不加是因为走向后建的边上一个ai会变大,第一次做贡献时上一个ai是a1,而a1变大只能走向1+a1+2,不一定是2,而走到其他点时上一个ai变化不受限(话说有没有大佬能给这个题一个详细的解释暴打我的xbb啊......)

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cmath> 
#include <algorithm> 
#include <queue> 
#include <map> 
#include <set> 
#include <bitset>
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
#define lson (x << 1)
#define rson (x << 1 | 1)
using namespace std;
template<typename xxx>inline void read(xxx &x) {
	x = 0;int f = 1;char c = getchar();
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') f = -1,c = getchar();
	for(;isdigit(c);c = getchar()) x = (x << 3) + (x << 1) + (c ^ '0');
	x *= f;  
}
template<typename xxx>inline void print(xxx x) {
	if(x < 0) {
		putchar('-');
		x = -x;
	}
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
}
const int maxn = 1000010;
const int mod = 1e9 + 7;
const int inf = 0x7f7f7f7f; 
struct edge{
	int to,last,val;
}e[maxn<<2];
int head[maxn],tot;
inline void add(int from,int to,int val) {
	++tot;
	e[tot].to = to;
	e[tot].val = val;
	e[tot].last = head[from];
	head[from] = tot;
}
int n;
struct node{
	int dis,pos;
	bool operator < (const node & x) const{
		return x.dis < dis;
	}
};
priority_queue<node>q;
int dis[maxn],vis[maxn];
inline void dj() {
	for(rint i = 0;i <= n + 1; ++i) {
		dis[i] = mod;
		vis[i] = 0;
	}
	q.push((node){0,1});dis[1] = 0;
	while(q.size()) {
		node x = q.top();q.pop();
		if(vis[x.pos]) continue;
		vis[x.pos] = 1;
		for(rint i = head[x.pos];i;i = e[i].last) {
			if(vis[e[i].to]) continue;
			if(dis[e[i].to] > dis[x.pos] + e[i].val) {
				dis[e[i].to] = dis[x.pos] + e[i].val;
				q.push((node){dis[e[i].to],e[i].to});
			}
		}
	} 
}
int main() {
	read(n);
	for(rint i = 1;i <= n; ++i) {
		int a;read(a);
		if(i > 1) add(i,i - 1,1),add(i,i + 1,1);
		if(i + a <= n) add(i,i + a + 1,0);
		else add(i,n + 1,i + a - n);
	}
	dj();
	print(dis[n + 1]); 
}
/*
*/
posted @ 2019-11-13 10:04  Thomastine  阅读(170)  评论(0编辑  收藏  举报