SCOI2013 day1 摩托车交易(motorcycle)
题目描述:
先吐槽一下为什么今年题要用纸质的…………又是版权问题么…………
然后数据因为版权…………没法得到,所以现在只能在电子科大OJ上提交题目(真搞不懂,数据什么时候也不公开了…………)。
首先很明显这道题要求我们找两点之间最小边的最大值,然后能买尽量买,能卖尽量卖,贪心走一遍就好了。考试的时候没有想出来正确的解法,于是上了一个类似弗洛伊德的DP,悲剧的是忘了处理列车站的情况,然后中间也是各种差错导致挂零…………悲剧的人生啊……
其实这个问题很简单,两点之间的最小边的最大值一定存在于最大生成树上(因为最大生成树上两点之间的路径是所有路径中包含的边中权值最大的几条),然后就成了在最大生成树上倍增了,此题瞬间变水题……无语啊……为什么我这么弱……………………T T
需要注意的:1.有列车站的城市需要缩成一个点来做。
2.中途的黄金有可能超过int,因此在倍增的时候返回INF的话一定要返回long long的INF。
我的代码,求神牛们轻虐……
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 #define min(a,b) ((a)<(b)?(a):(b)) 8 #define max(a,b) ((a)>(b)?(a):(b)) 9 const ll INF=0x3f3f3f3f3f3f3f3fll; 10 const int MAXN=100010; 11 const int MAXM=500010; 12 13 struct Edge 14 { 15 int st,ed,val; 16 bool operator < (const Edge &a) const 17 { 18 return val>a.val; 19 } 20 }edge[MAXM]; 21 struct Node 22 { 23 int end,val; 24 Node *next; 25 }edge2[MAXN<<1],*head[MAXN]; 26 27 int n,m,q,all,all2,gold[MAXN],ord[MAXN],lb[MAXN]; 28 int set_fa[MAXN],fa[MAXN][22],dis[MAXN][22],dep[MAXN]; 29 int que[MAXN]; 30 31 int find_set(int a) 32 { 33 if (set_fa[a]==a) return a; 34 return set_fa[a]=find_set(set_fa[a]); 35 } 36 void union_set(int a,int b) 37 { 38 int f1=find_set(a); 39 int f2=find_set(b); 40 if (f1!=f2) set_fa[f1]=f2; 41 } 42 void add_edge(int a,int b,int v) 43 { 44 edge[all].st=a,edge[all].ed=b,edge[all++].val=v; 45 } 46 void add_tree_edge(int a,int b,int v) 47 { 48 edge2[all2].end=b,edge2[all2].val=v,edge2[all2].next=head[a],head[a]=edge2+(all2++); 49 } 50 void make_tree() 51 { 52 int choose=0,all=-1; 53 if (!q) q=1; 54 while (choose<n-q) 55 { 56 ++all; 57 if (find_set(edge[all].st)!=find_set(edge[all].ed)) 58 { 59 ++choose; 60 add_tree_edge(edge[all].st,edge[all].ed,edge[all].val); 61 add_tree_edge(edge[all].ed,edge[all].st,edge[all].val); 62 union_set(edge[all].st,edge[all].ed); 63 } 64 } 65 int front=0,rear=1,t; 66 dep[que[rear]=(lb[1]?n+1:1)]=1; 67 while (front!=rear) 68 { 69 t=que[++front]; 70 for (Node *p=head[t];p;p=p->next) 71 if (p->end!=fa[t][0]) 72 { 73 fa[p->end][0]=t; 74 dis[p->end][0]=p->val; 75 dep[p->end]=dep[t]+1; 76 que[++rear]=p->end; 77 } 78 } 79 for (int k=1;k<=20;++k) 80 for (int i=1;i<=n+1;++i) 81 { 82 if (lb[i]) continue; 83 fa[i][k]=fa[fa[i][k-1]][k-1]; 84 dis[i][k]=min(dis[i][k-1],dis[fa[i][k-1]][k-1]); 85 } 86 } 87 ll get_val(int a,int b) 88 { 89 if (lb[a]) a=n+1; 90 if (lb[b]) b=n+1; 91 if (a==b) return INF; 92 int i;ll ans=INF; 93 if (dep[a]<dep[b]) swap(a,b); 94 for (i=20;~i;--i) if (dep[fa[a][i]]>=dep[b]) ans=min(ans,dis[a][i]),a=fa[a][i]; 95 if (a==b) return ans; 96 for (i=20;~i;--i) if (fa[a][i]!=fa[b][i]) ans=min(ans,min(dis[a][i],dis[b][i])),a=fa[a][i],b=fa[b][i]; 97 return min(ans,min(dis[a][0],dis[b][0])); 98 } 99 int main() 100 { 101 freopen("motorcycle.in","r",stdin); 102 freopen("motorcycle.out","w",stdout); 103 int x,y,z; 104 scanf("%d%d%d",&n,&m,&q); 105 for (int i=1;i<=n+1;++i) 106 set_fa[i]=i; 107 for (int i=1;i<=n;++i) 108 scanf("%d",&ord[i]); 109 for (int i=1;i<=n;++i) 110 scanf("%d",&gold[i]); 111 while (m--) 112 { 113 scanf("%d%d%d",&x,&y,&z); 114 add_edge(x,y,z); 115 } 116 for (int i=1;i<=q;++i) 117 { 118 scanf("%d",&x); 119 lb[x]=1; 120 } 121 for (int i=0;i<all;++i) 122 { 123 if (lb[edge[i].st]) edge[i].st=n+1; 124 if (lb[edge[i].ed]) edge[i].ed=n+1; 125 } 126 sort(edge,edge+all); 127 make_tree(); 128 ll now=max(gold[ord[1]],0),now_v; 129 if (gold[ord[1]]<0) puts("0"); 130 for (int i=2;i<=n;++i) 131 { 132 now_v=get_val(ord[i-1],ord[i]); 133 if (gold[ord[i]]>0) 134 now=min(now,now_v)+gold[ord[i]]; 135 else 136 { 137 now=min(now,now_v); 138 printf("%lld\n",min(-gold[ord[i]],now)); 139 now=max(now+gold[ord[i]],0); 140 } 141 } 142 return 0; 143 }