HDU 1285 肯定比賽名次

傳送門php

肯定比賽名次

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


c++

Problem Description
有 N個比賽隊(1<=N<=500),編號依次爲1,2,3,。。。。,N進行比賽,比賽結束後,裁判委員會要將全部參賽隊伍從前日後依次排 名,但如今裁判委員會不能直接得到每一個隊的比賽成績,只知道每場比賽的結果,即P1贏P2,用P1,P2表示,排名時P1在P2以前。如今請你編程序肯定 排名。
 
Input
輸入有若干組,每組中的第一行爲二個數N(1<=N<=500),M;其中N表示隊伍的個數,M表示接着有M行的輸入數據。接下來的M行數據中,每行也有兩個整數P1,P2表示即P1隊贏了P2隊。
 
Output
給出一個符合要求的排名。輸出時隊伍號之間有空格,最後一名後面沒有空格。
其餘說明:符合條件的排名可能不是惟一的,此時要求輸出時編號小的隊伍在前;輸入數據保證是正確的,即輸入數據確保必定能有一個符合要求的排名。
 
Sample Input
4 3
1 2
2 3
4 3
 
Sample Output
1 2 4 3
 
Author
SmallBeer(CML)
 
Source
 
Recommend
lcy
-------------------------------------------------------------------------------------------------------------------------
個人錯誤解法
 
#include <bits/stdc++.h>
using namespace std;
const int N(500+5);
vector<int> g[N];
bool vis[N];
int topo[N], tot;
void dfs(int u){
    vis[u]=1;
    for(int i=0; i<g[u].size(); i++){
        int &v=g[u][i];
        if(vis[v]) continue;
        dfs(v);
    }
    topo[--tot]=u;
}
int main(){
    for(int n, m; ~scanf("%d%d", &n, &m);){
        for(int i=1; i<=n; i++) g[i].clear();
        for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v);
        for(int i=1; i<=n; i++) sort(g[i].begin(), g[i].end(), greater<int>());
        memset(vis, 0, sizeof(vis)); tot=n;
        for(int i=n; i; i--) if(!vis[i]) dfs(i);
        printf("%d", topo[0]); for(int i=1; i<n; i++) printf(" %d", topo[i]); puts(""); 
    }
}

 

首先總的想法是 DFS拓撲排序,因爲題目要求輸出字典序最小的排列,對DFS的順序作一些修改:
(1)將每一個節點的鄰接表從大到小排序
(2)在主函數內,按照節點編號從大到小的順序調用DFS
這兩個修改雖然方向是對的,但仍是有問題的。
好比,樣例
5 4
5 2
2 4
5 3 
3 1
正確輸出是
5 2 3 1 4
但個人代碼輸出:
5 2 4 3 1
這個題目的輸出要解決的問題是:
保證 前後關係不肯定的節點中,序號小的在前。
(注意,上面用的詞是前後關係,而非 勝負關係。由於,假如知道了 A勝B, B勝C 那麼A, B, C三者的前後必定是 A B C 但A和C的勝負關係是不知道的。)
可否在不改變DFS框架的前提下,使輸出正確呢?
 ---------------------------------------------------------------------------------------
正解是:迭代
每次選擇 入度爲0且編號最小的點u輸出,將u刪除,並將u的臨接表中的點的入度減一。
(這種解法 不須要處理重邊
 
#include <bits/stdc++.h>
using namespace std;
const int N(500+5);
vector<int> g[N];
int in[N];
int main(){
    for(int n, m; ~scanf("%d%d", &n, &m);){
        for(int i=1; i<=n; i++) g[i].clear();
        memset(in, 0, sizeof(in));
        for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v), in[v]++;
        for(int i=0; i<n; )
            for(int u=1; u<=n; u++){
                if(in[u]==0){
                    if(!i++) printf("%d", u);
                    else printf(" %d", u);
                    in[u]=-1;
                    for(int j=0; j<g[u].size(); j++){
                        int &v=g[u][j]; in[v]--;
                    }
                    break;
                }
            }
        puts("");
    }
}
還可用 堆優化
#include <bits/stdc++.h>
using namespace std;
const int N(500+5);
vector<int> g[N];
int in[N];
typedef pair<int,int> P;
priority_queue<P, vector<P>, greater<P> > que;
int main(){
    for(int n, m; ~scanf("%d%d", &n, &m);){
        for(int i=1; i<=n; i++) g[i].clear();
        memset(in, 0, sizeof(in));
        for(int u, v; m--;) scanf("%d%d", &u, &v), g[u].push_back(v), in[v]++;
        for(int i=1; i<=n; i++) que.push({in[i], i});
        bool first=true;
        while(!que.empty()){
            P top=que.top(); que.pop(); int &u=top.second;
            if(in[u]!=top.first) continue;
            if(first) printf("%d", u), first=false;
            else printf(" %d", u);
            for(int i=0; i<g[u].size(); i++){
                int &v=g[u][i];
                que.push({--in[v], v});
            }
        }
        puts("");
    }
}
相關文章
相關標籤/搜索