• CF715B. Complete The Graph


    CF715B. Complete The Graph

    题意:

    给一张 n 个点,m 条边的无向图,要求设定一些边的边权
    使得所有边权都是正整数,最终 S 到 T 的最短路为 L

    1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000


    假做法:

    spfa求s到t最短路且满足可变边最少

    然后把不在最短路上的可变边标为inf,最短路上的可变边修改成使最短路长为L

    假的原因:

    其他的赋值为inf只是保证了经过其他可变边的路径不会更短,没有保证不经过其他可变边只是少经过了几条可变边、导致比最短路长的路径不会在最短路修改后更短

    存在绕过某条可变边的路径p,本来不是最短路且不经过最短路上可变边x,但你修改x之后,p会变成当前最短路,于是这个做法就挂掉了。

    就是说走了非可变边,把你修改的那条可变边绕过去了

    修正:

    真做法1:

    应当选择满足d<L的路径中经过可变边最少的一条

    可以在最短路上加维,(d(i,j))表示1到i经过j条可变边的最短路

    复杂度(O(mnlog{mn}))

    真做法2:

    随便求一条最短路,同样其他赋值inf,然后枚举最短路上的可变边,依次修改改可变边的值,修改后再求最短路看看会不会被绕过去。最后一定会收敛出答案

    无解:不经过可变边就可以<L,经过可变边也比L大

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5, M = 1e6+5;
    const ll inf = 1e16;
    
    int n, m, L, s, t;
    struct edge {int u, v, ne; ll w;} e[M];
    struct meow {int u, v; ll w;} a[M];
    int cnt=1, h[N], mark[M];
    inline void ins(int u, int v, ll w) {
    	if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
    	e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
    	e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
    	a[cnt>>1] = (meow) {u, v, w};
    }
    inline void paint(int x, ll v) {
    	a[x].w = v;
    	e[x<<1].w = e[x<<1|1].w = v;
    }
    
    ll d[N];
    int inq[N], pre[N];
    int q[N], head, tail;
    inline void lop(int &x) {if(x==N) x = 1;}
    void spfa0(int s) {
    	memset(d, 0x3f, sizeof(d));
    	head = tail = 1;
    	d[s] = 0; q[tail++] = s;  inq[s] = 1;
    	while(head != tail) {
    		int u = q[head++]; lop(head); inq[u] = 0;
    		for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
    			int v = e[i].v;
    			if(d[v] > d[u] + e[i].w) {
    				d[v] = d[u] + e[i].w;
    				if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
    			}
    		}
    	}
    }
    
    void spfa(int s) {
    	memset(d, 0x3f, sizeof(d));
    	memset(inq, 0, sizeof(inq));
    	head = tail = 1;
    	d[s] = 0; q[tail++] = s;  inq[s] = 1;
    	while(head != tail) {
    		int u = q[head++]; lop(head); inq[u] = 0;
    		for(int i=h[u]; i; i=e[i].ne) {
    			int v = e[i].v;
    			if(d[v] > d[u] + e[i].w ) {
    				d[v] = d[u] + e[i].w;
    				pre[v] = i;
    				if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
    			}
    		}
    	}
    }
    int chose[N];
    vector<int> li;
    int main() {
    	//freopen("in", "r", stdin);
    	ios::sync_with_stdio(false); cin.tie(); cout.tie();
    	cin >> n >> m >> L >> s >> t;
    	s++; t++;
    	for(int i=1; i<=m; i++) {
    		int u, v, w;
    		cin >> u >> v >> w;
    		u++; v++;
    		ins(u, v, w);
    	}
    	spfa0(s);
    	if(d[t] < L) {cout << "NO"; return 0;}
    	spfa(s);
    	if(d[t] > L) {cout << "NO"; return 0;}
    	if(d[t] == L) {
    		cout << "YES" << endl;
    		for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '
    ';
    		return 0;
    	}
    	
    	
    	int x = t;
    	while(x != s) {
    		if(mark[pre[x]]) chose[pre[x]>>1] = 1, li.push_back(pre[x]>>1);
    		x = e[pre[x]].u;
    	}
    	for(int i=1; i<=cnt>>1; i++) if(mark[i<<1] && !chose[i]) paint(i, inf);
    	for(int i=0; i<li.size(); i++) {
    		int now = li[i];
    		int delta = L - d[t] + 1;
    		paint(now, delta);
    		spfa(s);
    		if(d[t] == L) break;
    	}
    	cout << "YES" << endl;
    	for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '
    ';
    }
    
    
    

    ps:假做法的代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5, M = 1e6+5;
    const ll inf = 1e16;
    
    int n, m, L, s, t;
    struct edge {int u, v, ne; ll w;} e[M];
    struct meow {int u, v; ll w;} a[M];
    int cnt=1, h[N], mark[M];
    inline void ins(int u, int v, ll w) {
    	if(w == 0) w=1, mark[cnt+1] = mark[cnt+2] = 1;
    	e[++cnt] = (edge) {u, v, h[u], w}; h[u] = cnt;
    	e[++cnt] = (edge) {v, u, h[v], w}; h[v] = cnt;
    	a[cnt>>1] = (meow) {u, v, w};
    }
    
    ll d[N];
    int inq[N], cou[N], pre[N];
    int q[N], head, tail;
    inline void lop(int &x) {if(x==N) x = 1;}
    void spfa0(int s) {
    	memset(d, 0x3f, sizeof(d));
    	head = tail = 1;
    	d[s] = 0; q[tail++] = s;  inq[s] = 1;
    	while(head != tail) {
    		int u = q[head++]; lop(head); inq[u] = 0;
    		for(int i=h[u]; i; i=e[i].ne) if(!mark[i]) {
    			int v = e[i].v;
    			if(d[v] > d[u] + e[i].w) {
    				d[v] = d[u] + e[i].w;
    				if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
    			}
    		}
    	}
    }
    namespace test {
    	int pre[N];
    void spfa1(int s) {
    	memset(d, 0x3f, sizeof(d));
    	head = tail = 1;
    	d[s] = 0; q[tail++] = s;  inq[s] = 1;
    	while(head != tail) {
    		int u = q[head++]; lop(head); inq[u] = 0;
    		for(int i=h[u]; i; i=e[i].ne) {
    			int v = e[i].v;
    			if(d[v] > d[u] + e[i].w) {
    				d[v] = d[u] + e[i].w;
    				pre[v] = i;
    				if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
    			}
    		}
    	}
    }
    }
    void spfa(int s) {
    	memset(d, 0x3f, sizeof(d));
    	memset(cou, 0x3f, sizeof(cou));
    	memset(inq, 0, sizeof(inq));
    	head = tail = 1;
    	d[s] = 0; cou[s] = 0; q[tail++] = s;  inq[s] = 1;
    	while(head != tail) {
    		int u = q[head++]; lop(head); inq[u] = 0;
    		for(int i=h[u]; i; i=e[i].ne) {
    			int v = e[i].v;
    			if(d[v] > d[u] + e[i].w || (d[v] == d[u]+e[i].w && cou[v] > cou[u] + mark[i])) {
    				d[v] = d[u] + e[i].w;
    				cou[v] = cou[u] + mark[i];
    				pre[v] = i;
    				if(!inq[v]) q[tail++] = v, lop(tail), inq[v] = 1;
    			}
    		}
    	}
    }
    int chose[N];
    int main() {
    	//freopen("in", "r", stdin);
    	ios::sync_with_stdio(false); cin.tie(); cout.tie();
    	cin >> n >> m >> L >> s >> t;
    	s++; t++;
    	for(int i=1; i<=m; i++) {
    		int u, v, w;
    		cin >> u >> v >> w;
    		u++; v++;
    		ins(u, v, w);
    	}
    	spfa0(s);
    	if(d[t] < L) {cout << "NO"; return 0;}
    	spfa(s);
    	if(d[t] > L) {cout << "NO"; return 0;}
    	if(d[t] == L) {
    		cout << "YES" << endl;
    		for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '
    ';
    		return 0;
    	}
    	
    	int x = t;
    	int flag = 0;
    	while(x != s) {
    		if(mark[pre[x]]) chose[pre[x]>>1] = 1, flag = pre[x] >> 1;
    		x = e[pre[x]].u;
    	}
    	if(!flag) {cout << "NO"; return 0;}
    	for(int i=1; i <= cnt>>1; i++) if(mark[i<<1] && !chose[i]) a[i].w = inf;
    	for(int i=1; i<=cnt; i++) if(mark[i] && !chose[i>>1]) e[i].w = inf;
    	int delta = L - d[t] + 1;
    	a[flag].w = delta; 
    	e[flag<<1].w = e[flag<<1|1].w = delta;
    
    
    	test::spfa1(s);
    	if(d[t] != L) {
    		cout << d[t] << "nooooo
    ";
    		int x = t;
    		while(x != s) {
    			if(test::pre[x] != pre[x]) {
    				cout << "wrong
    ";
    				cout << mark[pre[x]] << "   " << mark[test::pre[x]] << '
    ';
    			}
    			x = e[pre[x]].u;
    		}
    	}
    	cout << "YES" << endl;
    	for(int i=1; i <= cnt>>1; i++) cout << a[i].u-1 << ' ' << a[i].v-1 << ' ' << a[i].w << '
    ';
    }
    
    
  • 相关阅读:
    laravel md5+salt 密码
    sql语句 当前时间查找重复 时间戳转换
    Supesite 参数说明
    ajax
    PDO操作
    laravel paginate动态分页
    PHP iconv()函数转字符编码的问题(转)
    计算几何基础模板(2014.10.6一直沿用)
    hdu 4893
    2014 ACM/ICPC 鞍山赛区网络赛(清华命题)
  • 原文地址:https://www.cnblogs.com/candy99/p/9286321.html
Copyright © 2020-2023  润新知