tarjan

/*
http://acm.hdu.edu.cn/showproblem.php?pid=4183
题意:在二维平面上给N个圆,每个圆的都有一种颜色光,每种颜色光的频率是不一样的。但保证一定有两种颜色:一种频率为400(最小),一种频率为789(最大)。
现在频率为400的为起点,频率为789的为终点。起点和终点是否能构成一个回路,且起点到终点的路径中光频率要单调递增,终点回到起点的路径中列频率单调递减。
思路:可以将圆看成一个点,圆之间相交看成点与点之间的边。这样就可以转化成在一个无向图里求给定点的环问题,因此可以直接套用tarjan求环。但要注意处理
无向图中的割点问题。至于路径的单调性,可以这样做,从起点出发,在没有走到终点时,保持路径都是按单调递增的走,当走过终点后,再找一条单调递减的路径回
到起点。

*/

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
const int maxn = 305;
struct NODE{
    double val;
    double x,y,r;
}node[305];
struct nd{
    int u,v,next;
}edge[305*305];
int map[305][305],ok,N,OK;
int vis[maxn],dfn[maxn],low[maxn],st[maxn],head[maxn];
int ecnt,cnt,idx,tp;
double as[maxn];

bool cmp(struct NODE a,struct NODE b)
{
    return a.val<b.val;
}
int Min(int x,int y){return x>y?y:x;}
void add(int u,int v)
{
    edge[ecnt].u = u;
    edge[ecnt].v = v;
    edge[ecnt].next = head[u];
    head[u] = ecnt++;
}
void init()
{
    memset(vis,0,sizeof(vis));
    memset(dfn,0,sizeof(dfn));
    memset(head,-1,sizeof(head));
    ecnt = idx = cnt = tp = ok = OK = 0;
}
void tarjan(int pre,int u)
{
    int i,v,t;
    dfn[u] = low[u] = ++idx;
    vis[u] = 1;
    st[++tp] = u;
    for(i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].v;
        if(v==pre)continue;
        if(!dfn[v]){
            if(!OK&&as[u]>=as[v])continue;
            if(OK&&as[u]<=as[v])continue;
            if(v==N)OK=1;
            tarjan(u,v);
            low[u] = Min(low[v],low[u]);
            if(low[v]>=dfn[u]){
                int flag = 0;
                cnt++;
                do{
                    t = st[tp--];
                    if(t==N)flag = 1;
                    vis[t] = 0;
                }while(t!=v);
                if((u==1)&&(low[v]==dfn[u])&&flag)ok = 1;
            }
        }else if(vis[v])low[u] = Min(dfn[v],low[u]);
    }
}
int main()
{
    int T,i,j;
    for(scanf("%d",&T);T--;)
    {
        scanf("%d",&N);
        for(i=1;i<=N;i++)
            scanf("%lf%lf%lf%lf",&node[i].val,&node[i].x,&node[i].y,&node[i].r);
        sort(node+1,node+N+1,cmp);
        for(i = 1; i <= N; ++ i) as[i] = node[i].val;
        memset(map,0,sizeof(map));
        for(i=1;i<=N;i++){
            for(j=i+1;j<=N;j++){
                if((pow(node[i].r+node[j].r,2)-(pow(node[i].x-node[j].x,2)+pow(node[i].y-node[j].y,2))>-1e-10)&&
                    (node[j].val-node[i].val>1e-10)){
                    map[i][j]=map[j][i]=1;
                }
            }
        }
        init();
        for(i = 1; i <= N; ++ i)
            for(j = 1; j <= N; ++ j) if(map[i][j])add(i,j);

        tarjan(-1,1);
        if(ok||map[1][N])puts("Game is VALID");
        else puts("Game is NOT VALID");
    }
    return 0;

posted on 2012-07-10 22:45  aigoruan  阅读(240)  评论(0)    收藏  举报

导航