P1186 玛丽卡

题目

题目

思路

其实这题原来不hack的时候可以dij+堆优化/spfaAC的,但是后来加了3个完全图数据,然后就悲剧了,其实有很多方法可以乱搞AC,比如说该题思路应该是枚举一开始最短路上的每条边然后对删除该边的情况跑spfa最后取最大值的,但是……嘿嘿嘿,我们可以枚举少一点,卡过时限,也可以用随机数枚举,按从小到大的方式枚举+枚举少一点(以上方法只使用了第一种卡时间,其他方式TLE概不负责),但是黑心良心的作者只给出能过原来数据的题解,剩下的……
· 革命尚未成功,同志们还需努力
嘿嘿嘿
code:

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int b[10011],last[10011],e=1,first[10011];
struct f{
	int to,r;
	int w;
	int net;
	bool cut;
} a[1100001];
bool book[10011];
struct f2{
	int x,y;
} p;
void read(int& x)
{
	x=0;
	int f=1;
	char ch=getchar();
	while (!isdigit(ch)) (ch=='-')&&(f=-1),ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x*=f;
	return; 
}
bool operator <(const f2 &x,const f2 &y)
{
	return x.x>y.x;
}
priority_queue<f2> c;
void jto(int x,int y,int z)
{
	a[e].to=y;
	a[e].r=x;
	a[e].w=z;
	a[e].net=first[x];
	first[x]=e;
	e++;
}
int n,m,q;
vector<int> o;
void f()
{
	for (int i=1;i<=n;i++)
	{
		b[i]=1000000010;
		book[i]=0;
	}
	b[q]=0;
	p.x=0,p.y=q;
	c.push(p);
	while (c.size())
	{
		int u=c.top().y;
		c.pop();
		if (book[u]) continue;
		book[u]=1;
		for (int i=first[u];i;i=a[i].net)
		{
			if (b[a[i].to]>b[u]+a[i].w)
			{
				b[a[i].to]=a[i].w+b[u];
				last[a[i].to]=i;
				p.x=b[a[i].to];
				p.y=a[i].to;
				c.push(p);
			}
		}
	}
	int y=1;
	while (y!=q)
	{
		o.push_back(last[y]);
		y=a[last[y]].r;
	}
	return;
}
int check()
{
	for (int i=1;i<=n;i++)
	{
		b[i]=1000000010;
		book[i]=0;
	}
	b[q]=0;
	p.x=0,p.y=q;
	c.push(p);
	while (c.size())
	{
		int u=c.top().y;
		c.pop();
		if (book[u]) continue;
		book[u]=1;
		for (int i=first[u];i;i=a[i].net)
		{
			if (a[i].cut==1) continue;
			if (b[a[i].to]>b[u]+a[i].w)
			{
				b[a[i].to]=a[i].w+b[u];
				p.x=b[a[i].to];
				p.y=a[i].to;
				c.push(p);
			}
		}
	}
	return b[1];
}
int main()
{
	read(n),read(m);
	q=n;
	int x,y,z,ans=-1;
	for (int i=1;i<=m;i++)
	{
		read(x),read(y),read(z);
		if (x==y) continue;
		jto(x,y,z);
		jto(y,x,z);
	}
	f();
	for (int i=0;i<o.size();i++)
	{
		a[o[i]].cut=1;
		a[o[i]^1].cut=1;
		ans=max(ans,check());
		a[o[i]].cut=0;
		a[o[i]^1].cut=0;
	}
	cout<<ans;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值