The King’s Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3120    Accepted Submission(s): 1096

Problem Description
In the Kingdom of Silence, the king has a new problem. There are N cities in the kingdom and there are M directional roads between the cities. That means that if there is a road from u to v, you can only go from city u to city v, but can’t go from city v to city u. In order to rule his kingdom more effectively, the king want to divide his kingdom into several states, and each city must belong to exactly one state. What’s more, for each pair of city (u, v), if there is one way to go from u to v and go from v to u, (u, v) have to belong to a same state. And the king must insure that in each state we can ether go from u to v or go from v to u between every pair of cities (u, v) without passing any city which belongs to other state.
  Now the king asks for your help, he wants to know the least number of states he have to divide the kingdom into.
 
Input
The first line contains a single integer T, the number of test cases. And then followed T cases.

The first line for each case contains two integers n, m(0 < n <= 5000,0 <= m <= 100000), the number of cities and roads in the kingdom. The next m lines each contains two integers u and v (1 <= u, v <= n), indicating that there is a road going from city u to city v.

 
Output
The output should contain T lines. For each test case you should just output an integer which is the least number of states the king have to divide into.
 
Sample Input
1
3 2
1 2
1 3
 
Sample Output
2
 
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = ;
const int MAXM = ;
struct Edge{
    int to, next;
}edge[MAXM];
int head[MAXN], tot;
int Low[MAXN], DFN[MAXN], Stack[MAXN], Belong[MAXN];
int Index, top;
int scc;
bool Instack[MAXN];
int num[MAXN];
int n, m;
void init() {
    tot = ;
    memset(head, -, sizeof(head));
}
void addedge(int u, int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void Tarjan(int u) {
    int v;
    Low[u] = DFN[u] = ++Index;
    Stack[top++] = u;
    Instack[u] = true;
    for (int i = head[u]; i != -; i = edge[i].next) {
        v = edge[i].to;        
        if (!DFN[v]) {
            Tarjan(v);
            if (Low[u] > Low[v]) Low[u] = Low[v];
        }
        else if (Instack[v] && Low[u] > DFN[v])
            Low[u] = DFN[v];
    }
    if (Low[u] == DFN[u]) {
        scc++;
        do {
            v = Stack[--top];
            Instack[v] = false;
            Belong[v] = scc;
            num[scc]++;
        } while (v != u);
    }
}
void solve() {
    memset(Low, , sizeof(Low));
    memset(DFN, , sizeof(DFN));
    memset(num, , sizeof(num));
    memset(Stack, , sizeof(Stack));
    memset(Instack, false, sizeof(Instack));
    Index = scc = top = ;
    for (int i = ; i <= n; i++)
        if (!DFN[i])
            Tarjan(i);
}
vector<int> g[MAXN];
int linker[MAXN], used[MAXN];
bool dfs(int u) {
    for (int i = ; i < g[u].size(); i++) {
        int v = g[u][i];
        if (!used[v]) {
            used[v] = ;
            if (linker[v] == - || dfs(linker[v])) {
                linker[v] = u;
                return true;
            }
        }
    }
    return false;
}
int hungary() {
    int res = ;
    memset(linker, -, sizeof(linker));
    for (int i = ; i <= scc; i++) {
        memset(used, , sizeof(used));
        if (dfs(i)) res++;
    }
    return scc - res;
}
int main() {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        scanf("%d%d", &n, &m);        
        init();
        int u, v;
        for (int i = ; i < m; i++) {
            scanf("%d%d", &u, &v);
            addedge(u, v);
        }
        solve();
        for (int i = ; i <= scc; i++) g[i].clear();
        for (int u = ; u <= n; u++) {
            for (int i = head[u]; i != -; i = edge[i].next) {
                int v = edge[i].to;
                if (Belong[u] != Belong[v])
                    g[Belong[u]].push_back(Belong[v]);
            } 
        }
        printf("%d\n", hungary());
    }
    return ;
}
 

hdu3861他的子问题是poj2762二分匹配+Tarjan+有向图拆点 其实就是求DAG的最小覆盖点的更多相关文章

  1. HDU 1068 Girls and Boys 二分图最大独立集(最大二分匹配)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. hdu 1281棋盘游戏(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281   Problem Description 小希和Gardon在玩一个游戏:对一个N*M的棋盘, ...

  3. hdu_5727_Necklace(二分匹配)

    题目连接:hdu_5727_Necklace 题意: 有2*n个珠子,n个阳珠子,n个阴珠子,现在要将这2n个珠子做成一个项链,珠子只能阴阳交替排,有些阳珠子周围如果放了指定的阴珠子就会变坏,给你一个 ...

  4. HDU 6178 Monkeys(树上的二分匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:现在有一n个顶点的树形图,还有k只猴子,每个顶点只能容纳一只猴子,而且每只猴子至少和另外一只猴子通过 ...

  5. hdu 2444 The Accomodation of Students 判断二分图+二分匹配

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  6. hdu 1281 棋盘游戏(二分匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    M ...

  7. LA 2038 Strategic game(最小点覆盖,树形dp,二分匹配)

    题意即求一个最小顶点覆盖. 对于没有孤立点的图G=(V,E),最大独立集+最小顶点覆盖= V.(往最大独立集加点) 问题可以变成求树上的最大独立集合. 每个结点的选择和其父节点选不选有关, dp(u, ...

  8. POJ 1274 The Perfect Stall、HDU 2063 过山车(最大流做二分匹配)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24081   Accepted: 106 ...

  9. [kuangbin带你飞]专题十 匹配问题 二分匹配部分

    刚回到家 开了二分匹配专题 手握xyl模板 奋力写写写 终于写完了一群模板题 A hdu1045 对这个图进行 行列的重写 给每个位置赋予新的行列 使不能相互打到的位置 拥有不同的行与列 然后左行右列 ...

随机推荐

  1. Linux系统管理第五六七章 权限及归属管理 磁盘管理 文件系统与lvm

    第五六七章   alias 查看系统别名   67 chmod 设置文件或目录的权限 -R表示以递归的方式设置目录及目录下的所有子目录及文件的权限 u:属主 g:属组 o:其他人 a:所有人 +:添加 ...

  2. 面向对象(OO)第二阶段学习总结

    0.前言 此阶段总共进行三次大作业,其中第一次作业中的第一题,水文数据校验及处理中,遇到较大的难题,第一次接触正则表达式,编码过程中显得难度特别大.第二次作业同样也是对于一元多项式求导中对单项的正则校 ...

  3. 【DNS域名解析命令】 ping

    ping, ping6 - send ICMP ECHO_REQUEST to network hosts ping命令向网络主机发送ICMP回传请求 详细描述: ping使用ICMP协议强制ECHO ...

  4. 交换机上的MAC地址表

    拓扑图: 1.首先在R1上的配置: R1(config)#int R1(config)#interface g R1(config)#interface gigabitEthernet 0/0 R1( ...

  5. Chrome最新版如何安装Proxy SwitchyOmega

    由于Chrome的代理设置与windows10的1703及以后的版本不兼容,导致无法使用代理功能,给工作带来了很大的不便.最近发现一款不错的Chrome代理插件Proxy SwitchyOmega,由 ...

  6. Codeforce-CodeCraft-20 (Div. 2)-C. Primitive Primes(本原多项式+数学推导)

    It is Professor R's last class of his teaching career. Every time Professor R taught a class, he gav ...

  7. python(文件操作)

    一.文件操作 1.tell()方法返回文件的当前位置,即文件指针当前位置. UTF-8 编码格式,一个中文占3个字符 GBK 编码格式,一个中文占2个字符 #写入前文件内容如下 "" ...

  8. python json.dumps中ensure_ascii的使用,load与loads的区别

    json模块最常用的两个功能: 一:json.dumps(),用于将dict拆分成str格式,称为序列化,注意序列化后,虽然print出来仍然显示的字典的样子,但是此时已经是str类型了. 其中,有时 ...

  9. 【漫画】JAVA并发编程三大Bug源头(可见性、原子性、有序性)

    原创声明:本文转载自公众号[胖滚猪学编程]​ 某日,胖滚猪写的代码导致了一个生产bug,奋战到凌晨三点依旧没有解决问题.胖滚熊一看,只用了一个volatile就解决了.并告知胖滚猪,这是并发编程导致的 ...

  10. 软件工程复习 WHUT

    软件过程模型: 瀑布模型:界限分明的独立阶段,计划驱动的软件过程.规范软件开发活动 (例如:可分为分析.开发.维护三个阶段) 也称生命周期模型.线性模型,采用结构化分析.设计.编程技术 不足的地方:知 ...