(中等) 动态规划 HOJ 2177 ICPC Strikes Again

来源:互联网 发布:碧柔防晒知乎 编辑:程序博客网 时间:2024/06/05 19:08

ICPC Strikes Again

My Tags  (Edit)
Source : South America 2005Time limit : 2 secMemory limit : 64 M

Submitted : 85, Accepted : 36

International Concrete Projects Company (ICPC) is a construction company which specializes in building houses for the high-end market. The company is the most profitable company in the world due to a very efficient land division method which has been used in its housing development projects since last year. Recently there was a chaos at ICPC, because employees refused to work arguing that they did not earn enough. Worried about the loss in profit due to the strike, the company board proposed a new method to calculate the salaries which was luckily accepted by everyone.

The salary of a worker reflects the significance of the tasks that he/she has to perform and is influenced by the way tasks depend on each other.

A task X depends on a task Y if either (i) X depends directly on Y , or (ii) there exists a task T such that X depends directly on T and T depends on Y . Since in ICPC all tasks must be performed, there is no circularity in the task dependence relation. Also, a task may be performed by more than one worker.

A basic significance is associated with each task reflecting its importance (for example, developing the efficient land division method is more important than building the houses themselves). The significance of a task T is then defined as the basic significance of T plus the significance of every task which depends directly on T. Note that if no other tasks depend directly on task T, the basic significance and the significance of T are the same. The salary of a worker is the sum of the significances of all the tasks he/she performs which do not depend on any other task performed by him/her. In other words, a value equal to the significance of task X will be added to the salary of a worker W that works in task X if there is no other task Y on which X depends, and W works also in Y .

ICPC wants you to help them to determine the salary of each of its employees.

Input

The input contains several test cases.

The first line of a test case contains two integers T and E indicating respectively the number of tasks and the number of employees (1 <= T <= 1000 and 1 <= E <= 1000). Tasks are numbered from 1 to T and employees from 1 to E.

Then it will come a sequence of lines describing the tasks 1 to T in ascending order. Each task is described by two lines. The first of these lines contains three integers BS, ND and NE, representing respectively the basic significance of the task, the number of tasks that depend directly on it, and the number of employees who perform it (1 <= BS <= 1000, 0 <= ND < T and 1 <= NE <= E). The second line contains ND+NE integers corresponding first to the ND directly dependent tasks and then the NE employees who perform the task.

The end of input is indicated by T = E = 0.

Output

Test cases must be answered in the order that they were presented. For each test case you must print:

  • a single line containing five stars ***** indicating the beginning of the case
  • for each employee i, one line with two integers i and s, separated by a blank, meaning that i has a salary of s.

Sample Input

3 2100 2 22 3 1 240 0 1160 0 127 210 2 12 3 110 2 14 5 210 2 16 7 210 0 1110 0 1110 0 1110 0 110 0

Sample Output

*****1 2002 200*****1 702 60

题意:给出各个任务的依赖关系,以及各个任务的工人,某项任务的价值是自己的基本价值+所有依赖该任务的价值 总和。而某项工人能得到的工资是他所操作的所有任务中,某些不依赖自己其他任务的那些任务的价值总和。需要求出每个工人的工资。

思路:对于一个节点如果该节点是i工人能得到工资节点,那么这个节点的后面的节点都不能成为i工人的工资的贡献者。于是我们从入度为0的点开始,把节点能否成为i工人的工资的状态一直传下去。最后求出每个节点能否成为某个工人的工资的一部分,那么答案就出来了

代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<map>
#include<queue>
#include<string.h>
#include<vector>
#include<stack>
#include<string>
using namespace std;

#define mp make_pair
const int maxn = 1000+10;
const int inf = 1e9;
#define LL long long

LL sum[maxn];
LL ans[maxn];
int ind[maxn];
vector<int> G[maxn];
vector<int> emp[maxn];
bool can[maxn][maxn];
bool vis[maxn];
int q[maxn*maxn];
int T, E;

void init()
{
for (int i = 1 ; i <= T ; ++i) emp[i].clear() , G[i].clear();
memset(ans,0,sizeof(ans));
memset(sum,0,sizeof(sum));
memset(ind,0,sizeof(ind));
}

void input()
{
int ND , NE;
for (int i = 1 ; i <= T ; ++i)
{
scanf("%d%d%d",&sum[i],&ND,&NE);
while (ND--)
{
int x;
scanf("%d",&x);
G[i].push_back(x);
++ind[x];
}
while (NE--)
{
int x;
scanf("%d",&x);
emp[i].push_back(x);
}
}
}

void dfs(int x)
{
if (vis[x]) return;
vis[x] = true;
for (int i = 0 ; i < G[x].size() ; ++i)
{
dfs(G[x][i]);
sum[x] += sum[G[x][i]];
}
}

void bfs()
{
memset(vis,0,sizeof(vis));
for (int i = 1 ; i <= T ; ++i)
for (int j = 1 ; j <= E ; ++j)
can[i][j] = true;
int front = 0 , rear = 0;
for (int i = 1 ; i <= T ; ++i) if (ind[i]==0)
q[rear++] = i , vis[i] = true;
while (front < rear)
{
int x = q[front++];
vis[x] = false;
for (int i = 0 ; i < G[x].size() ; ++i)
{
int y = G[x][i];
if (!vis[y])
{
q[rear++] = y;
vis[y] = true;
}
for (int j = 1 ; j <= E ; ++j) if (!can[x][j])
can[y][j] = false;
for (int j = 0 ; j < emp[x].size() ; ++j)
{
int em = emp[x][j];
can[y][em] = false;
}
}
}
}

void solve()
{
memset(vis,0,sizeof(vis));
for (int i = 1 ; i <= T ; ++i) if (ind[i]==0) 
dfs(i);
bfs();
for (int i = 1 ; i <= T ; ++i)
{
for (int j = 0 ; j < emp[i].size() ; ++j)
{
int em = emp[i][j];
if (can[i][em]) ans[em] += sum[i];
}
}
cout << "*****" << endl;
for (int i = 1 ; i <= E ; ++i)
cout << i << " " << ans[i] << endl;
}

int main()
{
while (scanf("%d%d",&T,&E)==2)
{
if (T+E==0) return 0;
init();
input();
solve();
}
}
0 0
原创粉丝点击