tarjan缩点,借鉴他人代码结果。
tarjan真的太难
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <stack>
//#include <stdlib.h>
#include <deque>
//#include <windows.h>
using namespace std;
long long r[1006],c[1006],tot,cnt,num,nn;
long long x[1006],y[1006];
bool maps[1006][1006],vis[1006];
int dfn[1006],belong[1006],low[1006],out[1006],in[1006];
stack<int>sta;
void tarjan(int u)
{
vis[u]=1;
sta.push(u);
dfn[u]=low[u]=++cnt;
for(int i=1;i<=nn;i++)
{
if(maps[u][i]==0) continue;
int v=i;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[u]) low[u]=low[v];
}
else if(vis[v])
{
if(dfn[v]<low[u]) low[u]=dfn[v];
}
}
if(dfn[u]==low[u])//搞出联通块了
{
++num;
while(true)
{
int v=sta.top(); sta.pop();
belong[v]=num;//缩点
vis[v]=0;
if(v ==u) break;
}
}
}
int main()
{
long long i,j,k,l,t,m,n,fina;
long long len;
scanf("%lld",&t);
for(long long xxx=1;xxx<=t;xxx++)
{
scanf("%lld",&n);nn=n;
memset(maps,0,sizeof maps);memset(dfn,0,sizeof dfn);
memset(vis,0,sizeof vis);memset(in, 0, sizeof(in));memset(out, 0, sizeof(out));
tot=cnt=num=0;
while(sta.size()) sta.pop();
for(i=1;i<=n;i++)
{
scanf("%lld",&x[i]);scanf("%lld",&y[i]);
scanf("%lld",&r[i]);scanf("%lld",&c[i]);
}
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)
{
len=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
if(len<=(r[i])*(r[i]))
maps[i][j]=1;
if(len<=(r[j])*(r[j]))
maps[j][i]=1;
}
}
for(i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int u=1;u<=n;u++)
{
for(i=1;i<=n;i++)
{
if(maps[u][i]==0) continue;
int v =i;
if(belong[u]!=belong[v])
{
out[belong[u]]++;
in[belong[v]]++;
}
}
}
fina=0;
for(i=1;i<=num;i++)
{
if(in[i]==0)
{
int mi=0x3f3f3f3f;
for(int j=1;j<=n;j++)
{
if(belong[j]==i)
{
if(c[j]<mi) mi=c[j];
}
}
fina+=mi;
}
}
printf("Case #%lld: %lld\n",xxx,fina);
}
return 0;
}