模板题 P3385,大概就是让你判断从节点 1 有没有能到的负权环。
虽然知道了应使用 SPFA 大法,但不知道为什么不能这样做(或者说是代码中有些什么毛病):
通过 tarjan 中找强连通分量的方法(也就是访问最浅的深度与其自己的深度的比较)找到环时,判断是否权值和为负来确认(代码中使用了根节点与节点路径长进行判断)。
代码:
/*
tarjan{if(deep[nextpos] > deep[pos] && dis[pos] < dis[nextpos])}
*/
#include <bits/stdc++.h>
using namespace std;
#define unclear -1
struct cell
{
int deep;
vector <int> con;
vector <int> wei;
int dis;
bool vis;
};
cell point[2005];
int pointnum;
void addedge(int frompos , int endpos , int wei)
{
point[frompos].con.push_back(endpos);
point[frompos].wei.push_back(wei);
}
void compute_init()
{
for(int i = 0;i < pointnum;i++)
point[i].vis = false;
point[0].deep = 0;
point[0].dis = 0;
}
bool compute_circle(int pos)
{
point[pos].vis = true;
for(unsigned long long int i = 0;
i < point[pos].con.size();i++)
{
int nextpos = point[pos].con[i];
if(point[nextpos].vis == true)
{
if(point[pos].dis + point[pos].wei[i] < point[nextpos].dis)
return true;
}
else if(point[nextpos].vis == false)
{
point[nextpos].deep = point[pos].deep + 1;
point[nextpos].dis = point[pos].dis + point[pos].wei[i];
if(compute_circle(nextpos) == true)
return true;
}
}
point[pos].vis = false;
return false;
}
int main()
{
int test_times , openum;
cin >> test_times;
while(test_times--)
{
cin >> pointnum >> openum;
for(int i = 0;i < pointnum;i++)
{
point[i].con.clear();
point[i].wei.clear();
}
{
int frompos , endpos , wei;
for(int i = 0;i < openum;i++)
{
cin >> frompos >> endpos >> wei;
if(wei >= 0)
{
addedge(frompos - 1 , endpos - 1 , wei);
addedge(endpos - 1 , frompos - 1 , wei);
}
else
addedge(frompos - 1 , endpos - 1 , wei);
}
}
compute_init();
cout << (compute_circle(0) == true ? "YES\n" : "NO\n");
}
return 0;
}
运行结果大多数 TLE,但鉴于我之前细节打错无 TLE 以及复杂度不高来看,他应该并不会 TLE。经数据后,发现他到了死循环中,问各位大佬如何改改。