【二分】电话网络

描述 Description
    由于地震使得连接汶川县城的电话线全部损坏,加入你是负责讲电话先接到震中汶川县城的负责人,汶川县城周围分布N(1<=n<=1000)根按1…n电话线杆间可以拉电话线,其余的由于地震使得无法被连接。
    第i对电话线杆的两个端点分别为Ai,Ri,它们间的距离为Li(1<=li<=1000000)。数据中保证每对最多只出现一次。编号为1的电话线杆已经接入了全国的电话网络,整个县城的电话线全部连到了编号为N的电话线杆上。也就是说,你的任务仅仅是找一条将1号和N号电话线杆连起来的路径,其余的电话线杆并不一定要连入电话网络。
    电信公司决定支援灾区免费为汶川县城连接K(0<=k     请你计算一下,将电话线引到震中汶川县城最少需要在电话线上花多少钱?
输入格式 Input Format
    输入文件的第一行包含三个用空格隔开的整数:N P和K。
    第二行到第P+1行:每行分别都为三个用空格隔开的整数:Ai Bi和Li。
输出格式 Output Format
    输出文件仅包含一个整数,表示在这项工程上的最小支出。如果任务不可能完成,则输出-1.

样例输入 Sample Input [ 复制数据]
5 7 1 1 2 5 3 1 4 2 4 8 3 2 3 5 2 9 3 4 7 4 5 6
样例输出 Sample Output [ 复制数据]
4
时间限制 Time Limitation

各个测试点1s


这道题比较好,因为不能用常规的二分思路,否则肯定超时。


普通的思路就是二分出最长的长度,然后搜索检验,n<=1000,果断超时,加之我一开始二分的时候,是二分的[minlen,maxlen]的连续区间,更加慢。若先排序再二分有可能的集合,速度略有优化。仍然过不了。


正确的方法是二分出第K+1长的边,前K长的边都可以直接免费,短于该边的边,因为不影响结果,所以可以不考虑它的长度。

而我们的验证,即是否存在方案,使我们二分出的长度为(第K+1)长或(小于K+1)长。明显去数长度大于二分长度的边最少有多少条!

于是采用最短路!先把长度小于等于二分长度的边临时设为0,大于二分长度的边临时设为1,从1到n求最短路,求出的结果就是长度大于二分长度的边的条数。


#include 
#include 
#include 
#include 
using std::sort;

long mid;
bool used[1010];
long map0[1010][1010];
long map[1010][1010];
long dist[1010];
long c[3010000];

long que[2000010];
long n, k;
const long qmod = 2000000;

long getint()
{
	long rs=0;bool sgn=1;char tmp;
	do tmp = getchar();
	while (!isdigit(tmp)&&tmp-'-');
	if (tmp == '-'){tmp=getchar();sgn=0;}
	do rs=(rs<<3)+(rs<<1)+tmp-'0';
	while (isdigit(tmp=getchar()));
	return sgn?rs:-rs;	
}

void spfa()
{
	memset(dist,0x3f,sizeof dist);
	long l = 0;
	long r = 0;
	r ++;
	que[r] = 1;
	dist[1] = 0;
	while (l < r)
	{
		l ++;
		if (l == qmod)
			l = 0;
		long u = que[l];
		used[u] = false;
		for (long v=1;vdist[u]+map[u][v])
			{
				dist[v] = dist[u] + map[u][v];
				if (!used[v])
				{
					used[v] = true;
					r ++;
					if (r == qmod)
						r = 0;
					que[r] = v;
				}
			}
		}
	}
}


bool can()
{
	for (long i=1;i k)
		return false;
	else
		return true;
}

bool check()
{
	for (long i=1;i>1;
		mid = c[mm];
		if (can())
		{
			if (ans > mid)
				ans = mid;
			r = mm-1;
		}
		else
		{
			l = mm+1;
		}
	}

	printf("%ld",ans);
	
	return 0;
}


你可能感兴趣的:(NOIP)