• 最短路建图


    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('
    '); 
    	} 
    }
    /*
    */
    

    [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]); 
    }
    /*
    */
    
  • 相关阅读:
    GUID
    Castle学习笔记二:框架结构及配置
    Linux编程基础
    Linux文件编程
    单臂路由配置实例
    CCNA学习笔记#02第7章操作与配置Cisco IOS
    Linux基本命令
    Linux系统中rar、unrar命令安装和使用详解
    批处理设置IP与DNS服务器
    Linux下载安装5笔输入法
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11847002.html
Copyright © 2020-2023  润新知