弱省互测#0 t3

Case 1 题意

要求给出下面代码的答案然后构造输入。
给一个图, n 个点 m 条边 q 次询问,输出所有点对之间最大权值最小的路径。

题解

把每一个询问的输出看成一条边,建一棵最小生成树。

Case 3 题意

给输出,要求构造输入使得用所给代码运行后得到的输出和给出的输出相同。
所给代码:n 次 Dijkstra 求两点间最短路

分析

考虑一下贪心。

题解

首先还是把每一条最短路的询问结果看成一条边,然后我们把这些边排序。
对于每一条边,如果这两个点现在的距离大于这条边的权值,我们就把这条边加进去,更新所有点对
的距离。
正确性显然。
现在证明这样做边数最短:
假设这样得到的构造方案为 A ,假设还有一种构造方案是 B ,并且边数更少。
那么在 A 中肯定存在一条边,在 B 中不存在。
于是在 B 中,这一条边的两个端点之间的距离,肯定大于 A 中这条边的边权。
否则如果相等的话,在 A 中就不会选择这一条边。
因此, B 这个方案肯定是非法的,也就是说, A 是边数最少的构造方案。

#include <bits/stdc++.h>
using namespace std;

namespace one {
	const int N=1015, M=1000015;
	struct E {
		int x, y, w;
	}e[M];
	int p[N], n, tot, m;
	bool cmp(const E &a, const E &b) {
		return a.w<b.w;
	}
	int find(int x) {
		return x==p[x]?x:p[x]=find(p[x]);
	}
	void work() {
		scanf("%d%d", &n, &m);
		printf("%d %d\n", n, m);
		int cnt=0;
		for(int i=1; i<=n; ++i) {
			for(int j=i+1; j<=n; ++j) {
				e[cnt].x=i;
				e[cnt].y=j;
				scanf("%d", &e[cnt].w);
				++cnt;
			}
		}
		for(int i=1; i<=n; ++i) {
			p[i]=i;
		}
		sort(e, e+cnt, cmp);
		for(int i=0; i<cnt; ++i) {
			int x=e[i].x, y=e[i].y, fx=find(x), fy=find(y), w=e[i].w;
			if(fx!=fy) {
				p[fx]=fy;
				++tot;
				printf("%d %d %d\n", x, y, w);
			}
		}
		for(; tot<=m; ++tot) {
			printf("%d %d %d\n", 1, 1, 0);
		}
	}
}
namespace two {
	const int mo1=9999991, mo2=3333331;
	typedef long long ll;
	int ipow(int a, int b, int mo) {
		int x=1;
		for(; b; b>>=1, a=(ll)a*a%mo) if(b&1) x=(ll)x*a%mo;
		return x;
	}
	void work() {
		int n;
		scanf("%d", &n);
		printf("%d\n", n);
		for(int i=1; i<=n; ++i) {
			static char s[100005];
			scanf("%s", s+1);
			int now1=0, now2=0, len=strlen(s+1);
			for(int i=1; i<=len; ++i) {
				now1=(now1*10+s[i]-'0')%mo1;
				now2=(now2*10+s[i]-'0')%mo2;
			}
			for(int x=1; x<=10000; ++x) {
				int h1=ipow(x, x, mo1), h2=ipow(x, x, mo2);
				if(h1==now1 && h2==now2) {
					printf("%d ", x);
					break;
				}
			}
		}
	}
}
namespace three {
	int d[1005][1005];
	struct E {
		int x, y, w;
	}e[1000005];
	bool cmp(const E &a, const E &b) {
		return a.w<b.w;
	}
	void work() {
		int n, m, cnt=0, tot=0;
		scanf("%d%d", &n, &m);
		printf("%d %d\n", n, m);
		for(int i=1; i<=n; ++i) {
			for(int j=i+1; j<=n; ++j) {
				e[cnt].x=i;
				e[cnt].y=j;
				scanf("%d", &e[cnt].w);
				cnt++;
			}
		}
		memset(d, 0x3f, sizeof d);
		for(int i=1; i<=n; ++i) {
			d[i][i]=0;
		}
		sort(e, e+cnt, cmp);
		for(int it=0; it<cnt; ++it) {
			int x=e[it].x, y=e[it].y, w=e[it].w;
			if(w<d[x][y]) {
				++tot;
				printf("%d %d %d\n", x, y, w);
				d[x][y]=d[y][x]=w;
				for(int i=1; i<=n; ++i) {
					for(int j=1; j<=n; ++j) {
						d[i][j]=min(d[i][j], min(d[i][x]+d[x][j], d[i][y]+d[y][j]));
					}
				}
			}
		}
		for(; tot<=m; ++tot) {
			printf("%d %d %d\n", 1, 1, 1);
		}
	}
}
namespace four {
	const int N=55005;
	vector<int> a[N];
	void work() {
		int n, root;
		scanf("%d%d", &n, &root);
		printf("%d %d\n", n, root);
		int csz=0, sz=pow(n, (double)2/3);
		for(int i=1; i<=n; ++i) {
			int blc;
			scanf("%d", &blc);
			csz+=a[blc].empty();
			a[blc].push_back(i);
		}
		int j, rt, na;
		for(j=0, na=a[csz].size(); j<na; ++j) {
			if(a[csz][j]==root) {
				swap(a[csz][j], a[csz][0]);
				break;
			}
		}
		for(int i=csz; i>=1; --i) {
			rt=a[i][0], j=1, na=a[i].size();
			for(; j<sz-1 && j<na; ++j) {
				printf("%d %d\n", a[i][j-1], a[i][j]);
			}
			if(j<na) {
				printf("%d %d\n", a[i][j++], root);
			}
			for(; j<sz*2-1 && j<na; ++j) {
				printf("%d %d\n", a[i][j-1], a[i][j]);
			}
			if(j<na) {
				printf("%d %d\n", a[i][j++], root);
			}
			for(; j<na; ++j) {
				printf("%d %d\n", a[i][j-1], a[i][j]);
			}
			if(root!=rt) {
				printf("%d %d\n", root, rt);
			}
		}
	}
}
namespace five {
	const int N=100015;
	struct E {
		int l, r, k, w;
	}e[N];
	bool cmp(const E &a, const E &b) {
		if(a.w==-1) {
			return 0;
		}
		if(b.w==-1) {
			return 1;
		}
		return a.w<b.w;
	}
	int a[N], K[N], vis[N], left, right;
	void work() {
		int n, t;
		scanf("%d%d", &n, &t);
		printf("%d %d\n", n, t);
		left=1; 
		right=n;
		int len=n/t, tot=0;
		for(int i=0; i<t; ++i) {
			int w;
			scanf("%d%d", &K[i], &w);
			if(w==-1) {
				continue;
			}
			e[tot].l=i*len+1, e[tot].r=i*len+len;
			e[tot].k=len-K[i]+1;
			e[tot].w=w;
			++tot;
		}
		sort(e, e+tot, cmp);
		for(int i=0; i<tot; ++i) {
			int l=e[i].l, k=e[i].k, w=e[i].w;
			for(int j=1; j<k; ++j, ++l) {
				while(vis[left]) {
					++left;
				}
				a[l]=left;
				vis[left]=1;
				++left;
			}
			a[l]=w;
			vis[w]=1;
		}
		for(int i=tot-1; i>=0; --i) {
			int r=e[i].r, k=e[i].k;
			for(int j=0; j<(len-k); ++j, --r) {
				while(vis[right]) {
					--right;
				}
				a[r]=right;
				vis[right]=1;
				--right;
			}
		}
		for(int i=1; i<=n; ++i) {
			if(a[i]) {
				continue;
			}
			while(vis[right]) {
				--right;
			}
			a[i]=right;
			--right;
		}
		for(int i=1; i<=n; ++i) {
			printf("%d ", a[i]);
		}
		for(int i=0; i<t; ++i) {
			printf("%d ", K[i]);
		}
	}
}
int main() {
	int C;
	scanf("%d", &C);
	printf("%d\n", C);
	if(C<20) one::work();
	else if(C<40) two::work();
	else if(C<60) three::work();
	else if(C<80) four::work();
	else five::work();
	return 0;
}
posted @ 2015-11-22 18:44  iwtwiioi  阅读(294)  评论(0编辑  收藏  举报