• zjoi 2008 knight 骑士 图论+动态规划


    【问题描述】

           Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英。他们劫富济贫,惩恶扬善,受到社会各界的赞扬。

           最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争。战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队。于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶。

           骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾。每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出征的。

           战火绵延,人民生灵涂炭,组织起一个骑士军团加入战斗刻不容缓!国王交给了你一个艰巨的任务,从所有的骑士中选出一个骑士军团,使得军团内没有矛盾的两人(不存在一个骑士与他最痛恨的人一同被选入骑士军团的情况),并且,使得这支骑士军团最具有战斗力。

           为了描述战斗力,我们将骑士按照1至N编号,给每名骑士一个战斗力的估计,一个军团的战斗力为所有骑士的战斗力总和。

    【输入文件】

           输入文件knight.in第一行包含一个正整数N,描述骑士团的人数。

           接下来N行,每行两个正整数,按顺序描述每一名骑士的战斗力和他最痛恨的骑士。

    【输出文件】

           输出文件knight.out应包含一行,包含一个整数,表示你所选出的骑士军团的战斗力。

    思路:题目中所给的条件本质就是一个环上连出去很多个树 DP

      1 #include<iostream>
    2 #include<cstring>
    3 #include<cmath>
    4 #include<cstdio>
    5 #include<algorithm>
    6 using namespace std;
    7 #define MAXN 1000001
    8 struct node
    9 {
    10 int num;
    11 bool w;
    12 node *next;
    13 };
    14 pair<int,int> ring[MAXN];
    15 node *graph[MAXN];
    16 node memo[2*MAXN];
    17 int Q_tree[MAXN],Q_circle[MAXN],d[MAXN],father[MAXN];
    18 long long a[MAXN],num[MAXN][2],dp[MAXN][2];
    19 int top=0,n;
    20 bool use[MAXN];
    21 void add(int x,int y)
    22 {
    23 node *p=&memo[top++];
    24 p->num=y; p->next=graph[x]; p->w=1; graph[x]=p;
    25 p=&memo[top++];
    26 p->num=x; p->next=graph[y]; p->w=0; graph[y]=p;
    27 }
    28 int find_circle(int i)
    29 {
    30 bool w=0;
    31 int left,right,u;
    32 Q_circle[left=right=1]=i;
    33 d[i]=1;
    34 father[i]=0;
    35 while(left<=right)
    36 {
    37 u=Q_circle[left];
    38 for(node *p=graph[u];p;p=p->next)
    39 if(p->w)
    40 {
    41 if(d[p->num]==0)
    42 {
    43 d[p->num]=d[u]+1;
    44 father[p->num]=u;
    45 Q_circle[++right]=p->num;
    46 }
    47 else
    48 {
    49 father[p->num]=u; w=1;
    50 break;
    51 }
    52 }
    53 if(w) break;
    54 left++;
    55 }
    56 int j=u;
    57 for(i=father[u];i!=u;i=father[i],j=father[j])
    58 ring[i]=make_pair(j,father[i]);
    59 ring[u]=make_pair(j,father[u]);
    60 return u;
    61 }
    62 void solve_tree(int i)
    63 {
    64 int left,right,u,j;
    65 memset(d,0,sizeof(d));
    66 d[i]=1; use[i]=1;
    67 Q_tree[left=right=1]=i;
    68 father[i]=0;
    69 while(left<=right)
    70 {
    71 u=Q_tree[left++];
    72 for(node *p=graph[u];p;p=p->next)
    73 if(p->num!=father[u])
    74 {
    75 if(u==i&&(ring[u].first==p->num||p->num==ring[u].second)) continue;
    76 use[p->num]=1;
    77 d[p->num]=d[u]+1;
    78 father[p->num]=u;
    79 Q_tree[++right]=p->num;
    80 }
    81 }
    82 for(j=right;j>0;j--)
    83 {
    84 u=Q_tree[j];
    85 num[u][0]=0;
    86 num[u][1]=a[u];
    87 for(node *p=graph[u];p;p=p->next)
    88 if(p->num!=father[u])
    89 {
    90 if(u==i&&(ring[u].first==p->num||p->num==ring[u].second)) continue;
    91 num[u][0]+=max(num[p->num][0],num[p->num][1]);
    92 num[u][1]+=num[p->num][0];
    93 }
    94 }
    95 }
    96 long long dynamic(int i)
    97 {
    98 long long ans=0;
    99 int j;
    100 dp[i][0]=num[i][0]; dp[i][1]=num[i][1];
    101 for(j=ring[i].first;j!=ring[i].second;j=ring[j].first)
    102 {
    103 dp[j][1]=dp[ring[j].second][0]+num[j][1];
    104 dp[j][0]=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
    105 }
    106 ans=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
    107 dp[i][0]=num[i][0]; dp[i][1]=num[i][0];
    108 for(j=ring[i].first;j!=i;j=ring[j].first)
    109 {
    110 dp[j][1]=dp[ring[j].second][0]+num[j][1];
    111 dp[j][0]=max(dp[ring[j].second][0],dp[ring[j].second][1])+num[j][0];
    112 }
    113 ans=max(ans,max(dp[ring[j].second][0],dp[ring[j].second][1]));
    114 return ans;
    115 }
    116
    117 long long solve(int i)
    118 {
    119 i=find_circle(i);
    120 int j;
    121 for(j=ring[i].first;j!=i;j=ring[j].first)
    122 solve_tree(j);
    123 solve_tree(j);
    124 return dynamic(j);
    125
    126
    127 }
    128 int main()
    129 {
    130 freopen("knight.in","r",stdin);
    131 freopen("knight.out","w",stdout);
    132 memset(num,0,sizeof(num));
    133 memset(use,0,sizeof(use));
    134 scanf("%d",&n);
    135 int i,x;
    136 long long ans=0;
    137 for(i=1;i<=n;i++)
    138 {
    139 scanf("%lld%d",a+i,&x);
    140 add(i,x);
    141 }
    142 for(i=1;i<=n;i++)
    143 if(!use[i])
    144 ans+=solve(i);
    145 printf("%lld\n",ans);
    146 return 0;
    147 }
    148



  • 相关阅读:
    svn:ignore 设置忽略文件
    Css让文字自适应Table宽度[转]
    自学python笔记
    java代码中添加log4j日志
    maven多模块项目搭建
    js || 与&&
    java内存溢出和tomcat内存配置
    xsl:for-each中引用循环外全局变量
    quartz启动两次(tomcat)
    pymysql简单封装
  • 原文地址:https://www.cnblogs.com/myoi/p/2432375.html
Copyright © 2020-2023  润新知