HDU 6311 Cover


Cover

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 440    Accepted Submission(s): 65
Special Judge


Problem Description
The Wall has down and the King in the north has to send his soldiers to sentinel.
The North can be regard as a undirected graph (not necessary to be connected), one soldier can cover one path. Today there's no so many people still breathing in the north, so the King wants to minimize the number of soldiers he sent to cover each edge exactly once. As a master of his, you should tell him how to arrange soldiers.
 

 

Input
There might be multiple test cases, no more than 20. You need to read till the end of input.
In the first line, two integers n and m, representing the number of nodes and edges in the graph.
In the following m lines, each contain two integers, representing two ends of an edge.
There are no parallel edges or self loops.
1n,m100000
 

 

Output
For each test case, the first line contains number of needed routes, p.
For the following p lines, an integer x in the beginning, followed by x integers, representing the list of used edges. Every integer should be a positive or negative integer. Its absolute value represents the number of chosen edge (1~n). If it's positive, it shows that this edge should be passed as the direction as the input, otherwise this edge should be passed in the direction different from the input. Edges should be in correct order.
 

 

Sample Input
3 3
1 2
1 3
2 3
 
Sample Output
1
3 1 3 -2
 

 

Source
 

 

Recommend
chendu
 
 
題目大意:給出一張無向圖,求出最少幾筆可以畫完所有的邊,並輸出路徑(反向邊輸出則要輸出 - (邊的序號))
 
聽了dls的講解並參考題解得到了一些自己的理解,基本做法就是
1:建圖
2:搜索連通塊和度為奇數的點
3:在每兩個奇數度點內額外加邊
4:dfs得到最終結果
 
一張連通圖需要n筆畫完則有 n = max ( |degree(奇數)| / 2 , 1)
 
 
 
試想每次添加一條邊,總度數 +2 ,當有新的筆畫出現,則說明出現了一個起點和終點,也就是度為奇數的點。
 
當圖上至多只有一對奇數度的點時,便可以一筆走過所有的邊
 
刪除額外添加的邊 (序號>2*m+1)得到結果
 
因為一開始dfs2沒有回溯的過程吃了n發WA......
(因為自信的覺得隨便選邊走一定可以達到目的,但實際上有些邊一遍走時過不去的,后來發現要依靠dfs的性質來走完所有邊)
 
AC代碼(姑且參考了題解):
#include<bits/stdc++.h>
#define N 100005
using namespace std;
struct Edge{
    int to,next;
    bool able;
}edge[N*4];///要多於總邊數的4倍 (*2雙向邊 並且可能加邊)

int n,m,
Degree[N],///每個點的度
Head[N],  ///每個點的最后一條加入的邊的序號
cnt,      ///邊的序號
res;      ///一共找到的路徑

bool vis[N];
vector<int>st;///保存一個連通塊中度為奇數的點
vector<int>road[N];

void add(int u,int v){
    edge[++cnt].next = Head[u];
    edge[cnt].to = v;
    edge[cnt].able = true;
    Head[u] = cnt;
    ++Degree[u];
}
inline void add_edge(int u,int v){
    add(u,v);
    add(v,u);
}

void dfs(int s){
    vis[s] = true;
    if(Degree[s]&1)st.push_back(s);
    for(int i = Head[s] ; i ; i = edge[i].next){
        if(!vis[edge[i].to])dfs(edge[i].to);
    }
}

void dfs2(int s){
    for(int i = Head[s] ; i ; i = edge[i].next){
        if(edge[i].able) {
            edge[i].able = edge[i ^ 1].able = false;
            dfs2(edge[i].to);
            if(i>2*m+1)++res;///說明此邊是由奇數度點添加得到的,所以這條回路已經結束
            else {
                road[res].push_back(i/2*(2*(i&1)-1));
            }
        }
    }
}

int main(){
    int u,v;
    while (cin>>n>>m){
        cnt = 1,res = 0;
        for(int i = 0 ; i < m ; ++i){
            scanf("%d %d",&u,&v);
            add_edge(u,v);
        }
        for(int i = 1 ; i <= n ; ++i){
            if(!vis[i] and Degree[i]) {
                dfs(i);///找到連通塊和奇數度的點
                if (st.empty()) {
                    st.push_back(i);
                    st.push_back(i);
                }
                for (int j = 2; j < st.size(); j += 2) {///為從第二對開始的奇數度的點添加一條雙向邊
                    add_edge(st[j], st[j + 1]);
                }
                res++;
                dfs2(st[0]);
                st.clear();
            }
        }
        printf("%d\n",res);
        for(int i = 1 ; i <= res ; ++i){
            printf("%d",road[i].size());
            for(int j = 0 ; j < road[i].size() ; ++j){
                printf(" %d",road[i][j]);
            }
            puts("");
            road[i].clear();
        }
        for(int i = 1 ; i <= n ; ++i){
            vis[i] = false;
            Head[i] = 0;
            Degree[i] = 0;
        }
    }
}

 

萌新瑟瑟發抖,請求指教。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM