1. 程式人生 > >BestCoder Round #1

BestCoder Round #1

約束 auto nbsp iss 項目管理軟件 man ont prior 大項目

逃生

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 569 Accepted Submission(s): 154


Problem Description 糟糕的事情發生啦,如今大家都忙著逃命。

可是逃命的通道非常窄,大家僅僅能排成一行。

如今有n個人,從1標號到n。同一時候有一些奇怪的約束條件。每一個都形如:a必須在b之前。


同一時候,社會是不平等的。這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些優點。

負責人如今能夠安排大家排隊的順序,因為收了優點。所以他要讓1號盡量靠前,假設此時還有多種情況,就再讓2號盡量靠前。假設還有多種情況。就讓3號盡量靠前,以此類推。



那麽你就要安排大家的順序。我們保證一定有解。


Input 第一行一個整數T(1 <= T <= 5),表示測試數據的個數。


然後對於每一個測試數據,第一行有兩個整數n(1 <= n <= 30000)和m(1 <= m <= 100000)。分別表示人數和約束的個數。

然後m行,每行兩個整數a和b,表示有一個約束a號必須在b號之前。

a和b必定不同。


Output 對每一個測試數據。輸出一行排隊的順序,用空格隔開。
Sample Input
1
5 10
3 5
1 4
2 5
1 2
3 4
1 4
2 3
1 5
3 5
1 2

Sample Output
1 2 3 4 5

Author CLJ 逆序拓補排序。 反向建圖。用優先隊列將大的放在前面。然後逆序輸出。
//453MS	2288K
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#define M 30007
using namespace std;
vector<int> v[M];
int in[M],ans[M],num,n;
void topsort()
{
    num=0;
    priority_queue<int>q;
    for(int i=1;i<=n;i++)
        if(!in[i]){q.push(i);}
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            for(int i=0;i<v[u].size();i++)
            {
                in[v[u][i]]--;
                if(!in[v[u][i]])q.push(v[u][i]);
            }
            ans[num++]=u;
        }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m;
        scanf("%d%d",&n,&m);
        memset(in,0,sizeof(in));
        for(int i=1;i<=n;i++)
            v[i].clear();
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            v[b].push_back(a);
            in[a]++;
        }
        topsort();
        for(int i=num-1;i>0;i--)
            printf("%d ",ans[i]);
        printf("%d\n",ans[0]);
    }
    return 0;
}


項目管理

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 725 Accepted Submission(s): 254


Problem Description 我們建造了一個大項目!這個項目有n個節點,用非常多邊連接起來。而且這個項目是連通的!


兩個節點間可能有多條邊。只是一條邊的兩端必定是不同的節點。


每一個節點都有一個能量值。

如今我們要編寫一個項目管理軟件,這個軟件呢有兩個操作:
1.給某個項目的能量值加上一個特定值。
2.詢問跟一個項目相鄰的項目的能量值之和。(假設有多條邊就算多次,比方a和b有2條邊。那麽詢問a的時候b的權值算2次)。


Input 第一行一個整數T(1 <= T <= 3),表示測試數據的個數。


然後對於每一個測試數據。第一行有兩個整數n(1 <= n <= 100000)和m(1 <= m <= n + 10),分別表示點數和邊數。



然後m行,每行兩個數a和b,表示a和b之間有一條邊。


然後一個整數Q。

然後Q行,每行第一個數cmd表示操作類型。假設cmd為0,那麽接下來兩個數u v表示給項目u的能量值加上v(0 <= v <= 100)。
假設cmd為1,那麽接下來一個數u表示詢問u相鄰的項目的能量值之和。

全部點從1到n標號。


Output 對每一個詢問,輸出一行表示答案。


Sample Input
1
3 2
1 2
1 3
6
0 1 15
0 3 4
1 1
1 3
0 2 33
1 2

Sample Output
4
15
15

Author CLJ
直接模擬就能夠。 假設用鄰接表來存會超時。用vector就過了。
//453MS	2288K
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#define M 30007
using namespace std;
vector<int> v[M];
int in[M],ans[M],num,n;
void topsort()
{
    num=0;
    priority_queue<int>q;
    for(int i=1;i<=n;i++)
        if(!in[i]){q.push(i);}
        while(!q.empty())
        {
            int u=q.top();
            q.pop();
            for(int i=0;i<v[u].size();i++)
            {
                in[v[u][i]]--;
                if(!in[v[u][i]])q.push(v[u][i]);
            }
            ans[num++]=u;
        }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int m;
        scanf("%d%d",&n,&m);
        memset(in,0,sizeof(in));
        for(int i=1;i<=n;i++)
            v[i].clear();
        int a,b;
        while(m--)
        {
            scanf("%d%d",&a,&b);
            v[b].push_back(a);
            in[a]++;
        }
        topsort();
        for(int i=num-1;i>0;i--)
            printf("%d ",ans[i]);
        printf("%d\n",ans[0]);
    }
    return 0;
}


BestCoder Round #1