hdu3861

来源:互联网 发布:大数据应用系统架构 编辑:程序博客网 时间:2024/06/04 19:32
/*唉~~英语不好理解不了题意。我是网上先看别人做的题意,在做题。 唉~~~~~~悲哀~~~题意:有个国王 要给自己的国家分块,然后给你一些路,两个城市可以互相到达的城市要在一个块(强连通分量),然后每个城市只能在一个快,然后一个强连通到另一个强联通分量有变得可以划分为一个块,问你最少花费的块数,理解好题意就好做了。思路:先用trajan算法缩点,然后重建图,重建图之后 就是一个最小路径覆盖了。*/#include<stdio.h>#include<string.h>#include<vector>using namespace std;int n,m;vector<int>map[5001];vector<int>map1[5001];int dfn[5001],low[5001];//dfn表示点被访问的次序,low[i]表示i点能够追溯到本个强联通分量最前访问次序的那个点的访问次序。int flag[5001];//标志素组int stack[5001];//用来保存已经访问了得点int color[5001];//染色int match[5001];int vis[5001];int c;int count=1,sign=0;int min(int x,int y){    if(x>y) return y;    return x;}int tarjan(int u){   flag[u]=1;    dfn[u]=low[u]=count++;    stack[++c]=u;//赋初值    for(int i=0;i<map[u].size();i++)    {   int v=map[u][i];        if(!flag[v])           {             tarjan(v);            low[u]=min(low[u],low[v]);           }             else if(flag[v]==1)low[u]=min(low[u],low[v]);    }    if(dfn[u]==low[u])    {        sign++;        do        {   //printf("%d ",stack[c]);            color[stack[c]]=sign;            flag[stack[c]]=-1;        }        while(stack[c--]!=u&&c>=0);    }} void  inint() {     for(int i=1;i<=n;i++)     {         map[i].clear();         map1[i].clear();     } } int find(int x) {     for(int i=0;i<map1[x].size();i++)     {         int v=map1[x][i];         if(!vis[v])         {             vis[v]=1;            if(match[v]==-1||find(match[v]))            {                match[v]=x;                return 1;            }         }     }     return 0; } int solve() {     memset(match,-1,sizeof(match));     int ans=0;     for(int i=1;i<=sign;i++)     {         memset(vis,0,sizeof(vis));         if(find(i)) ans++;     }     return ans; }int main(){    int t;    scanf("%d",&t);    while(t--)    { scanf("%d%d",&n,&m);      inint();      for(int i=1;i<=m;i++)      {          int x,y;          scanf("%d%d",&x,&y);          map[x].push_back(y);      }      sign=0;c=0;      memset(low,0,sizeof(low));      memset(dfn,0,sizeof(dfn));      memset(flag,0,sizeof(flag));      memset(color,0,sizeof(color));    for(int i=1;i<=n;i++)        if(!flag[i])tarjan(i);      for(int i=1;i<=n;i++)     {         for(int j=0;j<map[i].size();j++)         {             if(color[i]!=color[map[i][j]])             {                map1[color[i]].push_back(color[map[i][j]]);             }         }     }    printf("%d\n",sign-solve());    }}

原创粉丝点击