luogu1330 blocked sunlight University

topic

Title Description
Cao is a love of Brush Street Tsao, during the summer, he happily Brush Street campus in the sun every day. Cao cheerful crab see, feel uncomfortable. University of crab decided to block the sun, let Cao Brush Street.

Sunshine is not a campus consisting of N points, between N points connected by M roads to the map. Each crab can point to a blockade, after a certain point is blocked, the road to this point was blocked connected, Cao will not be able to brush up on the street with these roads. It is very tragic that the crab is a creature of discord, when two crab blocked the two adjacent points, they can conflict.

Ask: How many crab minimum required, you can block all roads and do not conflict.

Input format
First line: two integers N, M

Next M rows: two integers each row A, B, expressed a road connected between the point A to point B.

Output formats
only one line: If you can not block all roads crab, output "Impossible", otherwise the output an integer that represents how many crab requires a minimum.

Sample Input Output
Input # 1 replication
. 3. 3
1 2
1. 3
2. 3
Output # 1 replication
Impossible
input copy # 2
. 3 2
1 2
2. 3
outputs copy # 2
1
Description / Tips
[data size]

1 <= N <= 10000,1 <= M <= 100000, there is a path between any two points up.

analysis

Considering the questions you want to cover all sides, the deep search + staining be a good way

seriously(Joyfully) Wrote a deep-ready A search of this question, the results tragedy happened -

This chart is not necessarily connected graph QAQ.

So IGloriouslyBlown up, but thank God I still have 50 minutes ......

In fact, the solution is simple, deep search module can change (but to add stained Unicom block),
set in a side loop to enumerate the main module, add a stain marks China Unicom array block, has been dyed
Unicom will not have to block and then deep search

Then there is the protagonist - Deep Search

I only found deep search of points to put crab

Crab put a point labeled 1,
but not put crab it is connected to the point labeled 2,

If there is a conflict, this program does not work, you can return
a great value, and then choose from one of the least viable option in crab

He notes that each side should be covered, and only in the end put a crab, so just make sure the point is to put a crab, then cover the entire program Unicom block along with it OK,

So every discharge method Unicom crab only two blocks

I.e., the discharge point i and i crab crab hold point (point where i is an arbitrary point in the block Unicom)

Because they can not put crab two endpoints, the program may be a link block and u and v put crab discharge crab (u, v Unicom block start and end points on either side);

Because my deep search point found only put crab, in the master module only dfs (u), dfs (v), then the required number of crab comparing two schemes, the selected minimum value added ans ,like this:

Code

        
        cnt=0; mem(vis1);//记得初始化 
        //cnt记录该方案的河蟹数
        dfs(u);//假设起点放河蟹 
        int x=cnt;
        
        cnt=0;mem(vis1);
        dfs(v);//假设终点放河蟹 
        int y=cnt;
        
        
        if(x==1000000&&y==1000000)
        {//如果两种方法都不能覆盖所有的边,直接输出不可行 
            printf("Impossible");
            return;
        }
        ans+=Min(x,y);//选择两个方案中最小的 

In the deep search module, plus a double loop,

Enumeration of the first layer and the u (i.e. put a little crab) is connected to the other end side , labeled 2, wherein if there has been marked as 1, the conflict, return maxima

The second layer enumeration point v and the point of attachment can not put crab (except U) , the points must be placed crab, (v hold as crab), carried out
under a deep search is Ruoyi skip flag is 1, if it is marked as 2, and it must be put crab contradiction to return maximum value

for(int i=first[u];i;i=edge[i].nt)
//枚举与u相连的不能放河蟹的点 
    {
        int v=edge[i].v;
        if(vis1[v]==1) {cnt=1000000;return 0;}
        //如果终点也放了河蟹,则这种方案是不可行的 
        vis1[v]=2;
        //标记终点未放河蟹但不能再放河蟹 
        for(int j=first[v];j;j=edge[j].nt)
        //枚举下一层要放河蟹的点 
        {
            int v1=edge[j].v;
            //因为v不能放河蟹,则v1必须放河蟹 
            if(vis1[v1]==1) continue;
            //已经有一个端点有了河蟹 
            if(vis1[v1]==2) {cnt=1000000;return 0;}
            //两个都不能再放河蟹,则这条边不能被覆盖,该方案不可行 
            if(!dfs(v1)) return 0;//若该方案不行 
        }
    }

See also details of the code comments ~

/*
User:Mandy.H.Y
language:c++
Problem:1330
深搜,广搜,并查集都行 
*/
#include<bits/stdc++.h>
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define mem(A) memset((A),0,sizeof(A))

using namespace std;

const int maxn=10005;
const int maxm=100005;

int n,m,size=0,ans,cnt;
int first[maxn];
int vis[maxn],vis1[maxn];
//vis用于标记联通块
//vis1用于深搜染色 
struct Edge
{
    int u,v,nt;//存入起点的目的是为了标记联通块和深搜
}edge[maxm<<1];

template<typename T>inline void read(T &x)
{
    x=0;char c=getchar();bool f=0;
    while(c<'0'||c>'9') {f|=(c=='-');c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    if(f) x=-x;
}//读入优化 

template<typename T>void putch(const T x)
{
    if(x>9) putch(x/10);
    putchar((x%10)|48);
}

template<typename T>inline void put(const T x)
{
    if(x<0) putchar('-'),putch(-x);
    else putch(x);
}//输出优化 

void docu()
{
    freopen("1330.txt","r",stdin);
}

void eadd(int u,int v)
{
    edge[++size].v=v;
    edge[size].u=u;
    edge[size].nt=first[u];
    first[u]=size;
}//链表存边 

void readdata()//读入数据 
{
    read(n);read(m);
    for(int i=1;i<=m;++i)
    {
        int x,y;
        read(x);read(y);
        eadd(x,y);
        eadd(y,x);
    }
}

bool dfs(int u)//我只搜要放河蟹的点 
{
    vis[u]=1;//标记联通块 
    vis1[u]=1;//标记已放了河蟹 
    ++cnt;//cnt是已放河蟹的个数 
    for(int i=first[u];i;i=edge[i].nt)//枚举与u相连的不能放河蟹的点 
    {
        int v=edge[i].v;
        if(vis1[v]==1) {cnt=1000000;return 0;}//如果终点也放了河蟹,则这种方案是不可行的 
        vis1[v]=2;//标记终点未放河蟹但不能再放河蟹 
        for(int j=first[v];j;j=edge[j].nt)//枚举下一层要放河蟹的点 
        {
            int v1=edge[j].v;//因为v不能放河蟹,则v1必须放河蟹 
            if(vis1[v1]==1) continue;//已经有一个端点有了河蟹 
            if(vis1[v1]==2) {cnt=1000000;return 0;}//两个都不能再放河蟹,则这条边不能被覆盖,该方案不可行 
            if(!dfs(v1)) return 0;//若该方案不行 
        }
    }
    return 1;//若没有冲突 ,则此方案可行 
}

void work()
{
    ans=0;
    //注意,图不一定联通 ,所以要枚举边来标记联通块,这与我的深搜有关 
    for(int i=1;i<=(m<<1);i+=2)//枚举边,因为存的是无向边,所以m<<1(相当于m*2),
     //又因为同一条边是连续存的两次故i+=2 
    {
        int v=edge[i].v;
        int u=edge[i].u;
        if(vis[u]||vis[v]) continue;//如果已经遍历过这个联通块 
        
        cnt=0; mem(vis1);//记得初始化 
        dfs(u);//假设起点放河蟹 
        int x=cnt;
        
        cnt=0;mem(vis1);
        dfs(v);//假设终点放河蟹 
        int y=cnt;
        
        if(x==1000000&&y==1000000)
        {//如果两种方法都不能覆盖所有的边,直接输出不可行 
            printf("Impossible");
            return;
        }
        ans+=Min(x,y);//选择两个方案中最小的 
    }
    put(ans);
}

int main()
{
//  docu();
    readdata();//模块化虽然程序稍显冗长,但是调试很方便
    work();
    return 0;
}

Guess you like

Origin www.cnblogs.com/Mandy-H-Y/p/11354037.html