http://acm.hdu.edu.cn/showproblem.php?pid=5098
输入坑爹 算是存个模板..
加入a: b 那就建一条从b到a的边 题目就是找以入度为零的点为起点的含有最多需要重启的节点的一条链 以0为超级源点 向所有入度为零的点建一条边 如果哪个节点需要重启 那就把点权设为1 然后跑一边spfa
既然题目已经给定关系 那其实不管从哪开始都一样 权值最大的那条链是无论如何都要走的
#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f
struct node
{
int v;
int next;
};
map <string,int> mp;
queue <int> que;
node edge[100010];
int val[1010],first[1010],degree[1010],dis[1010],book[1010];
int n,num;
void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
}
int spfa()
{
int i,u,v,res;
while(!que.empty()) que.pop();
for(i=0;i<=n;i++)
{
dis[i]=-N;
book[i]=0;
}
que.push(0);
dis[0]=0;
book[0]=1;
while(!que.empty())
{
u=que.front();
que.pop();
book[u]=0;
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(dis[v]<dis[u]+val[v])
{
dis[v]=dis[u]+val[v];
if(!book[v])
{
que.push(v);
book[v]=1;
}
}
}
}
res=0;
for(i=1;i<=n;i++)
{
res=max(res,dis[i]);
}
return res;
}
int main()
{
string s,tmp;
int t,cas,i,j,len,flag,u,v;
char ch[2010];
scanf("%d",&t);
getchar();
getchar();
for(cas=1;cas<=t;cas++)
{
mp.clear();
memset(val,0,sizeof(val));
memset(first,-1,sizeof(first));
memset(degree,0,sizeof(degree));
n=0,num=0;
while(getline(cin,s)!=NULL)
{
if(s[0]=='\0') break;
istringstream sin(s);
sin>>ch;
len=strlen(ch);
flag=0;
for(i=0;i<len;i++)//
{
if(ch[i]=='*') flag=1;
}
ch[len-1-flag]='\0';
tmp=ch;
if(mp[tmp]==0) mp[tmp]=++n;
u=mp[tmp];
val[u]=flag;
while(sin>>tmp)
{
if(mp[tmp]==0) mp[tmp]=++n;
v=mp[tmp];
addedge(v,u);
degree[u]++;
}
}
for(i=1;i<=n;i++)
{
if(degree[i]==0)
{
addedge(0,i);
}
}
printf("Case %d: %d\n",cas,spfa());
}
return 0;
}