原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3879
题意:输入四个数n q s c ,n — 有n个队伍,q — 有q个服务器,s — 每个队伍的初始分数,c — 有c个操作;
对于每次操作,先输入一个数k,接下来k行,每行输入三个数a b c,表示a通过服务器c成功攻击了b;
对于每次的成功攻击,b都会减少n-1分,这n-1分会平分给通过同一个服务器攻击b的队伍;
接下来q行,每行n个数,1表示成功修复,0表示未修复;
未修复的队伍会减少n-1分,这n-1分平分给修复成功的队伍;
然后输入m个数,询问这m个队伍的分数以及排名;
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define exp 1e-5
bool vis[110][110][110];
bool vic[110];
struct node
{
int id, rank;
double score;
}w[110];
bool cmp1(node x, node y)
{
return x.score>y.score;
}
bool cmp2(node x, node y)
{
return x.id<y.id;
}
int main()
{
int cas;
scanf("%d", &cas);
while(cas--)
{
double s;
int n, q, c;
scanf("%d%d%lf%d", &n, &q, &s, &c);
for(int i = 1;i<=n;i++)
{
w[i].id = i;
w[i].rank = 1;
w[i].score = s;
}
while(c--)
{
int k;
scanf("%d", &k);
memset(vis, false, sizeof(vis));
while(k--)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
vis[a][b][c] = true;
}
for(int t = 1;t<=q;t++)
{
for(int j = 1;j<=n;j++)
{
int con = 0;
for(int i = 1;i<=n;i++)
{
if(vis[i][j][t])
con++;
}
if(con == 0)
continue;
w[j].score-=(n-1);
double val = 1.0*(n-1)/con;
for(int r = 1;r<=n;r++)
{
if(vis[r][j][t])
w[r].score+=val;
}
}
}
for(int i = 1;i<=q;i++)
{
memset(vic, false, sizeof(vic));
int con = 0;
for(int j = 1;j<=n;j++)
{
int x;
scanf("%d", &x);
if(!x)
{
w[j].score-=(n-1);
vic[j] = true;
con++;
}
}
if(con == n)
continue;
double val = 1.0*(n-1)*con/(n-con);
for(int t = 1;t<=n;t++)
{
if(!vic[t])
w[t].score+=val;
}
}
sort(w+1, w+n+1, cmp1);
for(int i = 1;i<=n;i++)
{
if(i!=1)
{
if(fabs(w[i].score-w[i-1].score)<exp)
w[i].rank = w[i-1].rank;
else
w[i].rank = i;
}
else
w[i].rank = i;
}
sort(w+1, w+n+1, cmp2);
int m;
scanf("%d", &m);
while(m--)
{
int x;
scanf("%d", &x);
printf("%f %d\n", w[x].score, w[x].rank);
}
}
}
return 0;
}