NOIP2015运输计划

COGS2109 http://cogs.pro:8080/cogs/problem/problem.php?pid=2109

洛谷交上去一直CE啊好绝望

COGS交了90分,一个点WA,一个点TLE嘤嘤嘤

恕我是在找不出来错误了

思路


先算LCA,深度,父节点什么的

二分答案,然后我们贪心的验证:

先找出所有应该改小的路径,记录个数和最大值,并差分地标记在在树上

随后DFS,找出所有应改小的路径都经过的边,即查询差分的值等于前面记录的个数的边

如果没找到,说明答案太苛刻了,放松一点

如果找到了,决定去掉其中权最大的那条边

如果这条边能让最长的路径合法,说明其他路径皆能合法,收紧答案

否则放松答案

然后完了,然而并不知道哪里错了

卡常好恶心

 1 #include<bits/stdc++.h> 
 2 using namespace std;
 3 #define N 300010
 4 inline bool isitdigit(char c){return c<='9'&&c>='0';}
 5 inline int maintain(int &a,int b){ return a>b?a:a=b;}
 6 inline int read()
 7 {
 8     register int s;register char c;
 9     while(!isitdigit(c=getchar()));
10     for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');
11     return s;
12 }
13 int findset[N];
14 inline int find(int x){return x==findset[x]? x:findset[x]=find(findset[x]);}
15 inline int merge(int a,int b){return find(a)==find(b)?0:findset[findset[a]]=findset[b];}
16 int n,m;
17 int head[N],to[N*2],next[N*2],value[N*2],tot;
18 struct ask{
19     int v,u,lca,dis;
20 }road[N];
21 int u[2*N],v[2*N],linking[2*N],enter[N],dis[N],deep[N],lca[2*N],cnt,maxdis,mark[N],father[N],maxside;
22 inline void add(int f,int t,int v){to[++tot]=t;value[tot]=v;next[tot]=head[f];head[f]=tot;}
23 inline void conect(int f,int t){u[++cnt]=f;v[cnt]=t;linking[cnt]=enter[f];enter[f]=cnt;}
24 void tarjan(int i,int f,int d)
25 {
26     father[i]=f;
27     deep[i]=d;
28     for(register int j=head[i];j;j=next[j]) if(to[j]!=f)
29     {
30         tarjan(to[j],i,d+value[j]);
31         merge(to[j],i);
32     }
33     for(register int j=enter[i];j;j=linking[j]) if(~deep[v[j]]) lca[j]=find(v[j]);
34 }
35 int dfs(int i,int f,int v)
36 {
37     int d=mark[i];
38     for(register int j=head[i];j;j=next[j]) if(to[j]!=f) d+=dfs(to[j],i,value[j]);
39     if(d==cnt) maintain(maxside,v);
40     return d;
41 }
42 
43 inline bool cal(int ans)
44 {
45     cnt=maxdis=maxside=0;
46     memset(mark,0,sizeof(mark));
47     for(register int i=1;i<=m;++i) if(road[i].dis>ans) 
48     {
49         cnt++,maintain(maxdis,road[i].dis);
50         mark[father[road[i].lca]]-=2;
51         mark[road[i].u]++,mark[road[i].v]++;
52     }
53     
54     dfs(1,0,0);
55     return maxdis-maxside<=ans;
56 }
57 
58 
59 int main()
60 {    
61     freopen("transport.in","r",stdin);
62     freopen("transport.out","w",stdout);
63     memset(deep,0xff,sizeof(deep));
64     n=read(),m=read();
65     for(register int i=1;i<=n;++i) findset[i]=i;
66     for(register int i=1;i<n;++i) 
67     {
68         int f=read();int t=read();int v=read();
69         add(f,t,v),add(t,f,v);
70     }
71     for(register int i=1;i<=m;++i) 
72     {
73         int f=read();int t=read();
74         conect(f,t),conect(t,f);
75     }
76     tarjan(1,0,0);
77     for(register int i=2;i<=cnt;i+=2) lca[i]==0? lca[i]=lca[i-1]:lca[i];
78     for(register int i=2;i<=cnt;i+=2) road[i>>1]=(ask){v[i],u[i],lca[i],deep[u[i]]+deep[v[i]]-(deep[lca[i]]<<1)}; 
79     int l=0,r=1000*n;
80     while(l<r)
81     {
82         int mid=(l+r)>>1;
83         if(cal(mid))r=mid;
84             else l=mid+1;
85     }
86     printf("%d",l);
87     return 0;
88 }

猜你喜欢

转载自www.cnblogs.com/MediocreKonjac/p/9101859.html