AtCoder Beginner Contest 061 - D Score Attack

給定一張邊帶權的有向圖。從節點\(1\)出發,每經過一條邊一次,得分加上這條邊的邊權。(可以多次經過,多次累加

必須在點\(n\)結束遊戲

判斷是否能使得分無限大,如果否,求最大得分。

sol

題目所給的邊權可以爲負,\(dfs\)判環+\(DAG\)\(DP\)最長路是補鋅的(?

然後很容易想到邊權取相反數,跑一遍\(SPFA\)判負環+求最短路。哇,sb題,秒了

然後喜提WA QAQ

被坑了————————————————

\(SPFA\)不可行的原因是,題目要求路徑從節點\(1\)到節點\(n\)。判出負環就輸出\(inf\)會少考慮一種情況,那就是負環並不在\(1\)\(n\)的路徑上。

所以我們用\(BellmanFord\)

先進行\(n-1\)輪鬆弛,記錄此時的\(dis[n]\)

再進行\(n-1\)輪鬆弛()新的\(dis[n]\)發生了變動,當且僅當在\(1\)\(n\)的路徑上存在負環。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n,m;
#define MAXN (2007)
#define MAXM (4014)
struct qwq
{
	int nex,to,w; 
}e[MAXM];
int h[MAXN],tot=0;
inline void add(int x,int y,int z)
{
	e[++tot].to=y;
	e[tot].w=z;
	e[tot].nex=h[x];
	h[x]=tot;
}
long long dis[MAXN];
int coun[MAXN];
bool vis[MAXN];
#include <queue>
#define inf (long long)((long long)(1e16)+233)
queue<int> q;
inline void INIT() { for (int i=1;i<=n;i++) dis[i]=inf; }
inline long long spfa()//關於SPFA,_____________
{
	INIT();
	q.push(1);
	vis[1]=true;
	dis[1]=0;
	int x;
	while (!q.empty())
	{
		x=q.front();
		vis[x]=false;
		q.pop();
		for (int i=h[x],y;i;i=e[i].nex)
		{
			y=e[i].to;
			
//			printf("x:%d dis:%lld  y:%d\n",x,dis[x],y);
			if (dis[y]>dis[x]+e[i].w)
			{
				dis[y]=dis[x]+e[i].w;
				if (!vis[y])
				{
					coun[y]=coun[x]+1;
					if (coun[y]>=n) return (inf<<1);
					vis[y]=true;
					q.push(y);
				}
			}
		}
	}
	return dis[n];
}
inline long long BF()
{
	INIT();
	dis[1]=0;
	for (int k=1;k<n;k++)
		for (int x=1;x<=n;x++)
			for (int i=h[x],y;i;i=e[i].nex)
			{
				y=e[i].to;
				
				if (dis[y]>dis[x]+e[i].w) dis[y]=dis[x]+e[i].w;
			}
	long long ans=dis[n];
	for (int k=1;k<n;k++)
		for (int x=1;x<=n;x++)
			for (int i=h[x],y;i;i=e[i].nex)
			{
				y=e[i].to;
				if (dis[y]>dis[x]+e[i].w) dis[y]=dis[x]+e[i].w;
			}
	if (ans!=dis[n]) return inf<<1;
	else return ans;
}
signed main()
{
	scanf("%d%d",&n,&m);
	for (int i=1,x,y,z;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,-z);
	}
	long long ans=BF();
	if (ans==inf<<1) puts("inf");
	else printf("%lld\n",-ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章