HDU 3749 Financial Crisis

Financial Crisis

题意:给一个图,包含N ( 3 <= N <= 5000 )个点, M ( 0 <= M <= 10000 )条边 and Q ( 1 <= Q <= 1000 )次查询.查询:两个点是否是点-双连通;

点-双连通:两点至少存在两条"点不重复"的路径;简称双连通(biconnected);

思路:直接调用dfs求割点的算法,其实也是Tarjan发明的,就是在判断出一个割点之后,就把栈S中该双连通分量的所有点(就在栈顶)insert到同一个集合中;

注意:一个点可以属于多个双连通分类,所以bccno数组其实只是一个防止重复insert同一个点,在set中可以除去。并且注意初始化各种数组即序号(这样都TLE几次)

PS:原本使用链式向前星来存储边,可是发现在hd里竟然比直接vector建图还慢。。(一脸茫然);并且开始使用stack<PII> 直接MLE了,可是看别人直接使用库栈。。

#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))

const int MAXN = 10010;
int low[MAXN],pre[MAXN],dfs_clock,bcc_cnt;
int bccno[MAXN];//看点属于哪个双连通分量;
set<int> bcc[MAXN];//存储每一个双连通分量的点的标号;
typedef pair<int,int> PII;
#define A first
#define B second
#define pb push_back
PII S[MAXN<<1];//存储边,从中取点
vector<int> e[MAXN];
int top;
int dfs(int u,int fa)
{
    int lowu = pre[u] = ++dfs_clock;
    int child = 0;
    rep0(i,0,e[u].size()){
        int v = e[u][i];
        PII e = PII{u,v};
        if(!pre[v]){
            S[++top] = e;
            child++;
            int lowv = dfs(v,u);
            lowu = min(lowu,lowv);//以子节点的low来更新u的low函数;
            if(lowv >= pre[u]){ //表示u-v为桥
                bcc[++bcc_cnt].clear();
                for(;;){
                    PII x = S[top--];
                    if(bccno[x.A] != bcc_cnt){bcc[bcc_cnt].insert(x.A);bccno[x.A] = bcc_cnt;}//就是为了不重复加点
                    if(bccno[x.B] != bcc_cnt){bcc[bcc_cnt].insert(x.B);bccno[x.B] = bcc_cnt;}
                    if(x.A == u && x.B == v) break;//根据加入的顺序知,正好对应;
                }
            }
        }
        else if(v != fa && pre[v] < pre[u]){
            S[++top] = e;
            lowu = min(lowu,pre[v]);
        }
    }
    return low[u] = lowu;
}
int f[MAXN];
int Find(int a)
{
    return a==f[a]?f[a]:f[a]=Find(f[a]);
}
char ans[][15] = {"zero","one","two or more"};
int main()
{
    int N,M,Q,kase = 1;
    while(scanf("%d%d%d",&N,&M,&Q) == 3 && N+M+Q){
        rep0(i,0,N){
            f[i] = i;
            e[i].clear();//直接vector建图
        }
        int u,v;
        rep0(i,0,M){
            scanf("%d%d",&u,&v);
            e[u].pb(v);e[v].pb(u);
            u = Find(u),v = Find(v);
            if(u != v) f[v] = u;
        }
        bcc_cnt = dfs_clock = top = 0;
        MS0(pre);MS0(bccno);
        rep0(i,0,N)if(pre[i] == 0)
            dfs(i,-1);
        printf("Case %d:\n",kase++);
        rep0(i,0,Q){
            int ret;
            scanf("%d%d",&u,&v);
            if(Find(u) != Find(v)) ret = 0;
            else{
                ret = 1;
                rep1(j,1,bcc_cnt){
                    if(bcc[j].find(u) != bcc[j].end() && bcc[j].find(v) != bcc[j].end()&&bcc[j].size() > 2)
                        ret = 2;
                }
            }
            printf("%s\n",ans[ret]);
        }
    }
    return 0;
}

时间: 2024-12-26 20:04:15

HDU 3749 Financial Crisis的相关文章

HDU 3749 Financial Crisis 经济危机(并查集,割点,双连通分量)

题意:给一个图n个点m条边(不一定连通),接下来又q个询问,询问两个点是为“不相连”,“仅有一条路径可达”,“有两条及以上的不同路径可达”三种情况中的哪一种.注:两条以上的路径指的是路径上的点连1个点也不重复. 思路:并查集+tarjan求割点. (1)情况一:先并查集处理,如果两个点从一开始就不连通,直接输出zero (2)情况二和情况三:两点既然连通,那么可能是只有1条路径,比如中间隔着一个割点:也可能有多条路径,比如在同一个双连通分量内.那么直接判断其是否在同一个双连通分量内即可,若在同一

HDU 1064 Financial Management

很简单 附代码 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 6 int main() 7 { 8 double a=0; 9 double sum=0; 10 //freopen("C:\\CODE\\in.txt", "r", stdin); 11 12 for(int i=0;i<12;i++){ 13 scanf("%lf&qu

题解报告——Financial Crisis

传送门 [思路分析] 这道题是一道双连通分量的板子题,我们只需要套个双联通分量,在用并查集判断连通性. 如果两个点连通且不在一个双连通分量里,那么就只存在唯一路径,否则存在多条(值得注意的是如果一个双连通分量只有两个点,那么就GG了,要排除这种情况). [代码实现] 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<cct

Most financial institutions 贪心 H

H - 贪心 Crawling in process... Crawling failed Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description Most financial institutions had become insolvent during financial crisis and went bankrupt or were bought b

HDU 4667 Building Fence(求凸包的周长)

A - Building Fence Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Status Description Long long ago, there is a famous farmer named John. He owns a big farm and many cows. There are two kinds of cows on his farm, o

POJ 3903 Stock Exchange

The world financial crisis is quite a subject. Some people are more relaxed while others are quite anxious. John is one of them. He is very concerned about the evolution of the stock exchange. He follows stock prices every day looking for rising tren

Uva - 1614 - Hell on the Markets

Most financial institutions had become insolvent during financial crisis and went bankrupt or were bought by larger institutions, usually by banks. By the end of financial crisis of all the financial institutions only two banks still continue to oper

【字源大挪移—读书笔记】 第二部分:字根

[2] 字根:[2.1]表示[否定]的字根.[2.2]表示[方位]的字根.[2.3]表示[程度]的字根.[2.4]表示[状态]的字根.[2.5]表示[现象]的字根.[2.6]表示[身体]的字根.[2.7]表示[姿势]的字根.[2.8]表示[心,心里活动]的字根.[2.9]表示[行为动作]的字根.[2.10]表示[感官动作]的字根.[2.11]表示[感觉]的字根.[2.12]表示[生命]的字根.[2.13]表示[死亡]的字根.[2.14]表示[社会]的字根 [2.1]表示[否定]的字根 -neg-

ZOJ 3524 Crazy Shopping

Crazy Shopping Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. Original ID: 352464-bit integer IO format: %lld      Java class name: Main Because of the 90th anniversary of the Coherent & Cute Patchouli (C.C.P), Kawashiro