bzoj 1912: [Apio2010]patrol 巡逻

呵呵呵呵呵呵,自己画图,大概半个小时,觉的连上边会成环(是不是该交仙人掌了??)然后求环不重合部分最大就好了,

结果写了一坨DP,最后写不下去了,再次扒了题解。

发现我真的是个sb。

k==1,直接是直径

k==2,搞出直径然后把直径删掉(把权值赋为-1,再找直径)(有点像我一开始想的每次找个最长链去贪心,然而,,总觉得,这种题贪心这么可能对)

  1 /*#include <bits/stdc++.h>
  2 #define LL long long
  3 #define lowbit(x) x&(-x)
  4 #define inf 0x3f3f3f3f
  5 #define N 100005
  6 using namespace std;
  7 inline int ra()
  8 {
  9     int x=0,f=1; char ch=getchar();
 10     while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
 11     while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
 12     return x*f;
 13 }
 14 int head[N],cnt,n,f[N][3][3],k;
 15 struct edge{int next,to;}e[N<<1];
 16 void insert(int x, int y){e[++cnt].next=head[x]; e[cnt].to=y; head[x]=cnt;}
 17 void dfs(int x, int fa)
 18 {
 19     int mx1=0,mx2=0,mx3=0,mx4=0;
 20     for (int i=head[x];i;i=e[i].next)
 21     {
 22         if (e[i].to==fa) continue;
 23         dfs(e[i].to,x);
 24         int orz=f[e[i].to][0][1],flag=1,hehe=1;
 25         if (orz<=mx1 && orz<=mx2 && orz<=mx3 && orz>mx4) mx4=orz;
 26         if (orz<=mx1 && orz<=mx2 && orz>mx3) mx4=mx3,mx3=orz;
 27         if (orz<=mx1 && orz>mx2) mx4=mx3,mx3=mx2,mx2=orz,hehe=0;
 28         if (orz>mx1) mx4=mx3,mx3=mx2,mx2=mx1,mx1=orz,flag=0;
 29         if (f[x][1][1] && k)
 30         {
 31             if (!flag)
 32                 f[x][2][0]=max(f[x][2][0],f[x][1][1]+mx1+1);
 33             else if (!hehe) f[x][2][0]=max(f[x][2][0],f[x][1][1]+mx2+1);
 34         }
 35         cout<<f[x][1][1]<<endl;
 36         if (f[x][1][0] && k) f[x][1][1]=max(f[x][1][1],f[x][1][0]+mx1+1);
 37         cout<<f[x][1][1]<<endl;
 38         if (f[e[i].to][1][0] && mx2 && k) f[x][1][1]=max(f[x][1][1],1+f[e[i].to][1][0]+flag?mx1:mx2);
 39         if (f[e[i].to][1][1] && k) f[x][1][1]=max(f[x][1][1],f[e[i].to][1][1]+1);
 40         if (f[e[i].to][1][1] && mx2 && k) f[x][2][0]=max(f[x][2][0],1+f[e[i].to][1][1]+flag?mx1:mx2);
 41         if (f[e[i].to][2][0] && k) f[x][2][0]=max(f[x][2][0],f[e[i].to][2][0]);
 42         if (f[x][1][0] && f[e[i].to][1][0] && k) f[x][2][0]=max(f[x][2][0],f[x][1][0]+f[e[i].to][1][0]);
 43         f[x][1][0]=max(f[x][1][0],max(mx1+mx2+1,f[e[i].to][1][0]));
 44         f[x][0][1]=mx1+1;
 45         if (f[3][1][1]==3) {cout<<x<<"  "<<e[i].to; while (1);}
 46     }
 47     printf("%d %d %d %d %d\n",x,f[x][0][1],f[x][1][0],f[x][1][1],f[x][2][0]); system("pause");
 48 }
 49 int main(int argc, char const *argv[])
 50 {
 51     n=ra(); k=ra(); k--;
 52     for (int i=1; i<n; i++)
 53     {
 54         int x=ra(),y=ra();
 55         insert(x,y); insert(y,x);
 56     }
 57     dfs(1,0);
 58     printf("%d\n",n*2-f[1][k+1][0]);
 59     return 0;
 60 }*/
 61 #include <bits/stdc++.h>
 62 #define LL long long
 63 #define lowbit(x) x&(-x)
 64 #define inf 0x3f3f3f3f
 65 #define N 100005
 66 using namespace std;
 67 inline int ra()
 68 {
 69     int x=0,f=1; char ch=getchar();
 70     while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();}
 71     while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
 72     return x*f;
 73 }
 74 int mx,n,k,tot,cnt=1,len;
 75 int head[N];
 76 int s1[N],s2[N];
 77 struct edge{
 78     int to,next,v;
 79 }e[N<<1];
 80 void insert(int x, int y){
 81     e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].v=1; head[x]=cnt;
 82 }
 83 int dfs(int x, int fa)
 84 {
 85     int mx1=0,mx2=0;
 86     for (int i=head[x];i;i=e[i].next)
 87     {
 88         if (e[i].to==fa) continue;
 89         int v=e[i].v+dfs(e[i].to,x);
 90         if (v>mx1) mx2=mx1,mx1=v,s2[x]=s1[x],s1[x]=i;
 91         else if (v>mx2) mx2=v,s2[x]=i;
 92     }
 93     if (mx1+mx2>len) len=mx1+mx2,mx=x;
 94     return mx1;
 95 }
 96 int main(int argc, char const *argv[])
 97 {
 98     n=ra(); k=ra(); tot=2*(n-1);
 99     for (int i=1; i<n; i++)
100     {
101         int x=ra(),y=ra();
102         insert(x,y);
103         insert(y,x);
104     }
105     dfs(1,0); tot-=len-1;
106     if (k==2)
107     {
108         len=0;
109         for (int i=s1[mx];i;i=s1[e[i].to]) e[i].v=e[i^1].v=-1;
110         for (int i=s2[mx];i;i=s1[e[i].to]) e[i].v=e[i^1].v=-1;
111         dfs(1,0); tot-=len-1;
112     }
113     cout<<tot;
114     return 0;
115 }
时间: 2024-12-26 16:06:03

bzoj 1912: [Apio2010]patrol 巡逻的相关文章

bzoj 1912 : [Apio2010]patrol 巡逻 树的直径

题目链接 如果k==1, 显然就是直径. k==2的时候, 把直径的边权变为-1, 然后在求一次直径. 变为-1是因为如果在走一次这条边, 答案会增加1. 学到了新的求直径的方法... #include <bits/stdc++.h> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<

BZOJ 1912:[Apio2010]patrol 巡逻(树直径)

1912: [Apio2010]patrol 巡逻 Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离. Sample Input 8 1 1 2 3 1 3 4 5 3 7 5 8 5 5 6 Sample Output 11 HINT 10%的数据中,n ≤ 1000, K = 1: 30%的数据中,K

【BZOJ 1912】 [Apio2010]patrol 巡逻

1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 669 Solved: 380 [Submit][Status][Discuss] Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离. S

【bzoj1912】 Apio2010—patrol 巡逻

http://www.lydsy.com/JudgeOnline/problem.php?id=1912 (题目链接) 题意 给出一棵树,要求在树上添加K(1 or 2)条边,添加的边必须经过一次,使得从1号节点到达每个节点最后返回1号节点所经过的路径最短. Solution 如果不添加边,那么答案一定是每条边经过两次. 如果K为1,那么答案就很明显对吧,找到树的直径,链接直径两端点,使得直径上的边只经过一次,答案最优. 那么如果K为2,我们会发现,当两个环有变重叠时,重叠的边同样是要经过2次.

BZOJ1912 [Apio2010]patrol 巡逻

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小

P1912: [Apio2010]patrol 巡逻

这道题讨论了好久,一直想不明白,如果按传统的随便某一个点出发找最长链,再回头,K=2 的时候赋了-1就没法用这种方法找最长链了,于是乎,更强的找最长链的方法就来了..类似于DP的东西吧.先上代码: 1 const maxn=100002; 2 type 3 node=record 4 f,t,l:longint; 5 end; 6 var n,k,i,j,ans,num,f,t,diameter,s,sum:longint; 7 b:array[0..2*maxn] of node; 8 hea

【BZOJ】【1912】【APIO2010】patrol巡逻

树形DP 说是树形DP,其实就是求树的最长链嘛…… K=1的时候明显是将树的最长链的两端连起来最优. 但是K=2的时候怎么搞? 考虑第一次找完树的最长链以后的影响:第一次找过的边如果第二次再走,对答案的贡献会变成-1,因为两次都选这一段的话,反而会使得这一段不得不走两次(如果只被选一次的话就可以只走一次),所以就将第一次找出的树的最长链上的边权值都改为-1.这个操作可以用链表实现(类比一下最小费用最大流的spfa实现!) 题解:http://blog.csdn.net/qpswwww/artic

【BZOJ-1912】patrol巡逻 树的直径 + DFS(树形DP)

1912: [Apio2010]patrol 巡逻 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1034  Solved: 562[Submit][Status][Discuss] Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示村庄a与b之间有一条道路(1 ≤ a, b ≤ n). Output 输出一个整数,表示新建了K 条道路后能达到的最小巡逻距离.

BZOJ 1912 巡逻(树直径)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1912 题意:给出一棵树,边权为1.现在加一条或两条边后,使得从1出发遍历每个点至少一次再回到1的路程最短. 思路:先求一次树的直径Max1.然后将直径的边权改为-1,再求一次直径Max2.答案为ans=(n-1)*2-(Max1-1)-(Max2-1). struct node { int u,v,w,next; }; node edges[N<<1]; int head[N],e;