最小树形图uva11865

//此题主要是注意某些点虽然阔以一直不断追溯然后出环但是那个点不一定在环上。对于已经遍历过的点就不要重新遍历了,否则容易出现环数偏大然后导致streamint noot possible的情况
//对于这种经常涉及修改的题目函数设计的时候还是传参数比较好
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
struct edgee
{
	int from, to, value,band;
	edgee(int from, int to, int value, int band) :from(from), to(to), value(value), band(band)
	{}
	edgee()
	{}
};
int pre[1000], visit[1000], minn[1000], belong[4000];
int n, m, cost, edgetot;
int root;
edgee edge[100000];
bool test(int pointtot,int band)
{
	long long ans = 0;
	while (1)
	{
		 int circlenum = 0;
		for (int i = 0; i < pointtot; i++)minn[i] = 1000000000, pre[i] = -1, belong[i] = -1, visit[i] = -1;
		for (int i = 0; i < m; i++)
		{
			int from = edge[i].from, to = edge[i].to;
			if (from != to&&edge[i].band >= band&&minn[to] > edge[i].value)
			{
				pre[to] = from; minn[to] = edge[i].value;
			}
		}
		for (int i = 0; i < pointtot; i++)
		{
			if (i == root)continue;
			if (minn[i] == 1000000000)return false;
		}
		for (int i = 0; i < pointtot; i++)
		{
			if (i != root)ans += minn[i];
			if (i == root || visit[i] != -1)continue;
			int temp = i; 
			while (temp != root&&visit[temp] == -1)
			{
				visit[temp] = i;
				temp = pre[temp];
			}
			if (visit[temp] == i)
			{
				int q = temp;
				while (pre[temp] != q)
				{
					belong[temp] = circlenum;
					temp = pre[temp];
				}
				belong[temp] = circlenum;
				circlenum++;
			}
		}
		if (circlenum == 0)break;
		for (int i = 0; i < pointtot; i++)if (belong[i] == -1)belong[i] = circlenum++;
		for (int i = 0; i < edgetot; i++)
		{
			if (belong[edge[i].from] != belong[edge[i].to])	edge[i].value -= minn[edge[i].to];
			edge[i].from = belong[edge[i].from];
			edge[i].to = belong[edge[i].to];
		}
		pointtot = circlenum;
		root = belong[root];
	}
	if (ans <= cost)
		return true;
	else
		return false;
}
int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d%d%d", &n, &m, &cost);
		edgetot = 0;
		int l = 1000000000, r = -1;
		for (int i = 0; i < m; i++)
		{
			scanf("%d%d%d%d", &edge[edgetot].from, &edge[edgetot].to, &edge[edgetot].band, &edge[edgetot].value);
			edge[i + m] = edge[i];
			l = min(l, edge[edgetot].band); r = max(r, edge[edgetot].band);
				edgetot++;
		}
		root = 0;
		if (!test(n,l))
		{
			printf("streaming not possible.\n");
		}
		else
		{
			while (r > l)
			{
				int mid = l + (r - l + 1) / 2;
				for (int i = 0; i < m; i++)edge[i] = edge[i + m];
				root = 0;
				if (test(n,mid))
					l = mid;
				else
					r = mid - 1;
			}
			printf("%d kbps\n", l);

		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值