随笔-72  评论-126  文章-0  trackbacks-0
很好玩的算法
强连通+缩点可以把一块点看成一个点,大大加快算法。还有一些无法解决的问题也可以用这个来解决
前几天在林学院做题的时候胡搞搞出来了,哈哈
今天又A了一道
最近对图对树越来越有感觉了

http://acm.hdu.edu.cn/showproblem.php?pid=2767
#include "stdio.h"
#include 
"algorithm"
using namespace std;
#define maxn 20001
struct Node {
    
int to;
    Node 
* next;
}list[maxn],opp[maxn];
struct SCC{
    
int time;
    
int newid;
    
int idx;
}hh[maxn];
int time,newid;
bool flag;
bool hash[maxn];
bool hashid[maxn];
bool gashid[maxn];
//--------------------------------------------
void dfs(int idx) {
    Node 
* buf;
    buf 
= list[idx].next;
    
while(buf) {
        
if(!hash[buf->to]) {
            hash[buf
->to] = true;
            dfs(buf
->to);
        }
        buf 
= buf->next;
    }
    
if(time == 7)
        time 
= 7;
    hh[idx].time 
= time ++;
    hh[idx].idx 
= idx;
}
void dfs2(int idx) {
    Node 
* buf;
    buf 
= opp[idx].next;
    
while(buf) {
        
if(!hash[buf->to]) {
            hash[buf
->to] = true;
            dfs2(buf
->to);
        }
        buf 
= buf->next;
    }
    hh[idx].newid 
= newid;
}
void dfs3(int idx) {
    Node 
* buf;
    buf 
= list[idx].next;
    
while(buf) {
        
if(hh[idx].newid != hh[buf->to].newid) {
            hashid[hh[idx].newid] 
= true;
            gashid[hh[buf
->to].newid] = true;
        }
        
if(!hash[buf->to]) {
            hash[buf
->to] = true;
            dfs3(buf
->to);
        }
        buf 
= buf->next;
    }
}
bool cmp(SCC a,SCC b) {
    
return a.time > b.time;
}
//-----------------------------------------
int main() {
    
int n,i,a,b,m,T;
    Node 
* buf;
    scanf(
"%d",&T);
    
while(T--) {
        scanf(
"%d%d",&n,&m);
        
for(i = 1 ; i <= n ; i ++) {
            list[i].next 
= NULL;
            opp[i].next 
= NULL;
        }
        
while(m --) {
            scanf(
"%d%d",&a,&b);
            buf 
= (Node *)malloc(sizeof(Node));        //正图
            buf->to = b;
            buf
->next = list[a].next;
            list[a].next 
= buf;

            buf 
= (Node *)malloc(sizeof(Node));        //反图
            buf->to = a;
            buf
->next = opp[b].next;
            opp[b].next 
= buf;
        }
        memset(hash,
false,sizeof(bool)*(n+1));
        time 
= 0;
        
for(i = 1 ; i <= n ; i ++) {                //先确定时间戳
            if(!hash[i]) {
                hash[i] 
= true;
                dfs(i);
            }
        }
        sort(hh
+1,hh+1+n,cmp);                        //按时间戳排序
        memset(hash,false,sizeof(bool)*(n+1));
        newid 
= 0;
        
for(i = 1 ; i <= n ; i ++) {                //把点分成几块
            if(!hash[hh[i].idx]) {
                hash[hh[i].idx] 
= true;
                hh[hh[i].idx].newid 
= ++newid;
                dfs2(hh[i].idx);
            }
        }
        
if(newid == 1) {
            puts(
"0");
            
continue;
        }
        memset(hash,
false,sizeof(bool)*(n+1));
        memset(hashid,
false,sizeof(bool)*(newid+1));
        memset(gashid,
false,sizeof(bool)*(newid+1));
        
for(i =1 ; i <= n ; i ++) {                    //找出块的出度入度
            if(!hash[i]) {
                hash[i] 
= true;
                dfs3(i);
            }
        }
        
int cnt = 0;
        
int cnt1 = 0;
        
for(i = 1; i <= newid ; i ++) {
            
if(!hashid[i])
                cnt 
++;
            
if(!gashid[i])
                cnt1 
++;
        }
        printf(
"%d\n",cnt>cnt1?cnt:cnt1);
    }
    
return 0;
}


posted on 2009-05-17 20:36 shǎ崽 阅读(600) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理