开始悲剧的tle了。。。又检查了一遍代码。。发现没有错啊!!!最后逛了一下神犇们的博客发现了这段话!!!!!“spfa的时候沿途记录每个点是由哪个点更新来的。那么,在第n+1次入队的时候的那个循环,我们就一定可以得到一个负权环。顺着最后那个点往前找环。注意!由于更新的复杂性,最后那个点不一定在最终负环里(依赖于spfa的写法)”
fuck!!!
next,我隐约感觉spfa判断负圈应该可以优化啊!!?否则那个进出 n 次后跳出和水的一逼的 bellman-ford 算法有什么区别!!!!尼玛有什么区别啊!!!复杂度就差不多了啊!!!还不如直接用 bellman-ford 啊!!!!!!!!有木有啊!!!可是怎么优化呢....?
#include<vector>
#include<cstring>
#include<string>
#include<cstdio>
#include<iomanip>
#include<queue>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<map>
#include<cassert>
#include<cmath>
#include<stack>
using namespace std;
#define abs(a) ((a)>0?(a):-(a))
const int maxn = 111;
const int maxc = 222;
const int end = 201;
const int add = 100;
const int inf = 0x3f3f3f3f;
int n,m,over;
int x10[maxn];
int y10[maxn];
int x20[maxn];
int y20[maxn];
int fb[maxn];
int tc[maxn];
int back[maxc];
int way[maxc];
int num[maxc];
int c[maxc][maxc];
int fnm[maxn][maxn];
int f[maxc][maxc];
int cost[maxc][maxc];
vector<int>g[maxc];
queue<int>q;
bool inq[maxc];
bool vis[maxc];
void init()
{
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
memset(cost,0,sizeof(cost));
memset(back,-1,sizeof(back));
memset(fnm,0,sizeof(fnm));
for(int i=0;i<=end;i++)
{
g[i].clear();
}
return ;
}
inline int d12(int x10, int y10, int x20, int y20)
{
return abs( x10 - x20) + abs( y10 - y20) + 1;
}
void build()
{
for(int i=1;i<=n;i++)
{
c[0][i] = fb[i];
}
for(int i=1;i<=m;i++)
{
c[i+add][end] = tc[i];
}
int now,to;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
now = i;
to = j+add;
c[now][to] = inf;
f[now][to] = fnm[i][j];
f[to][now] = -fnm[i][j];
f[0][now] += fnm[i][j];
f[now][0] -= fnm[i][j];
f[to][end] += fnm[i][j];
f[end][to] -= fnm[i][j];
}
}
for(int i=1;i<=n;i++)
{
g[0].push_back(i);
g[i].push_back(0);
}
for(int i=1;i<=m;i++)
{
now = i + add;
g[now].push_back(end);
g[end].push_back(now);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
now = i;
to = j + add;
g[now].push_back(to);
g[to].push_back(now);
}
}
int temp;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
now = i;
to = j + add;
temp = d12 ( x10[i], y10[i], x20[j], y20[j] );
cost[now][to] = temp;
cost[to][now] = -temp;
}
}
return ;
}
bool spfa()
{
build();
int now,to;
for(int i=0;i<=n;i++)
{
way[i] = inf;
}
for(int i=1;i<=m;i++)
{
now = i+add;
way[now] = inf;
}
memset(inq,false,sizeof(inq));
while(!q.empty())
{
q.pop();
}
q.push(end);
inq[end] = true;
way[end] = 0;
int temp;
memset(num,0,sizeof(num));
while(!q.empty())
{
now = q.front();
q.pop();
for(int i=0;i<g[now].size();i++)
{
to = g[now][i];
if( c[now][to] > f[now][to] )
{
temp = way[now] + cost[now][to];
if(temp < way[to])
{
back[to] = now;
way[to] = temp;
num[to]++;
if(num[to] > maxc)
{
over = to;
return true;
}
if(!inq[to])
{
inq[to] = true;
q.push(to);
}
}
}
}
inq[now] = false;
}
return false;
}
int find()
{
memset(vis,false,sizeof(vis));
int temp = over;
while(true)
{
if(vis[temp])
{
return temp;
}
vis[temp] = true;
temp = back[temp];
}
assert(false);
}
void zz1215()
{
if(spfa())
{
int temp = find();
over = temp;
int now,to;
while(true)
{
if(back[temp] == over)
{
f[over][temp] ++;
f[temp][over] --;
break;
}
now = back[temp];
to = temp;
f[now][to]++;
f[to][now]--;
temp = back[temp];
}
printf("SUBOPTIMAL\n");
// cout<<"SUBOPTIMAL"<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
now = i;
to = j+add;
printf("%d ",f[now][to]);
// cout<<f[now][to]<<" ";
}
printf("%d\n",f[i][m+add]);
// cout<<f[i][m+add]<<endl;
}
}
else
{
printf("OPTIMAL\n");
// cout<<"OPTIMAL"<<endl;
}
return ;
}
int main()
{
// cin>>n>>m;
while(cin>>n>>m)
{
init();
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x10[i],&y10[i],&fb[i]);
// cin>>x10[i]>>y10[i]>>fb[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x20[i],&y20[i],&tc[i]);
// cin>>x20[i]>>y20[i]>>tc[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&fnm[i][j]);
// cin>>fnm[i][j];
}
}
zz1215();
}
return 0;
}