AmazingCounters.com

两道图论题 - HZOI2014.10.30

传送门:http://pan.baidu.com/s/1qW6tgS0

 

T1:

由于题目中要求的东西不好妨碍正常的最短路进行,那么可以枚举它。

也就是二分答案+最短路检测,我写的dijk+heap+读入优化过了

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<algorithm>
  7 using namespace std;
  8 const int N = 10010;
  9 const int M = 50010;
 10 #define For(i,n) for(int i=1;i<=n;i++)
 11 #define Rep(i,l,r) for(int i=l;i<=r;i++)
 12 
 13 struct EDGE{
 14     int s,t,w;
 15     int next;
 16 }E[M*2];
 17 
 18 struct Node{
 19     int node,dis;
 20     bool operator <(const Node & A) const{
 21         return A.dis<dis;
 22     }
 23 }save[N];
 24 bool used[N];
 25 int cost,cnt,n,m,u,v,s,key[N],costs[N],Max;
 26 
 27 void makelist(EDGE A){
 28     A.next = key[A.s];E[++cnt] = A;key[A.s] = cnt;
 29 }
 30 
 31 void read(int &v){
 32     char ch=getchar();
 33     int num=0;
 34     while(ch<'0'||ch>'9') ch=getchar();
 35     while(ch>='0'&&ch<='9'){
 36         num=num*10+ch-'0';
 37         ch=getchar();
 38     }
 39     v=num;
 40 }
 41 
 42 void init(){
 43     read(n);read(m);read(u);read(v);read(s);
 44     For(i,n) { 
 45         read(costs[i]);
 46         Max=max(costs[i],Max); 
 47     }
 48     For(i,m){
 49         EDGE T;
 50         read(T.s);read(T.t);read(T.w);
 51         makelist(T);
 52         swap(T.s,T.t);makelist(T);
 53     }
 54 }
 55 
 56 int Dijkstra(int Lim){
 57     priority_queue<Node> q;
 58     memset(used,0,sizeof(used));
 59     Node a,b;int tot=0;
 60     a.node = u;a.dis = 0;
 61     if(costs[u]>Lim) return -1; 
 62     b.node=b.dis=0;
 63     q.push(a);
 64     while(!q.empty()){
 65         Node Head = q.top();q.pop();
 66         int p = key[Head.node];
 67         used[Head.node]=true;
 68         if(Head.node == v) return 1;
 69         while(p){
 70             if(E[p].w+Head.dis<=s&&costs[E[p].t]<=Lim&&!used[E[p].t]){
 71                 b.dis = E[p].w+Head.dis;
 72                 b.node = E[p].t;
 73                 q.push(b);
 74             }p=E[p].next;
 75         }
 76         while(!q.empty()&&used[q.top().node]) q.pop();
 77     }
 78     return -1;
 79 }
 80 
 81 bool Check(int Lim){
 82     if(Dijkstra(Lim)==-1) return false;
 83     return true;
 84 }
 85 
 86 int main(){
 87     init(); 
 88     int Left=1,Right=Max;
 89     while(Right-Left>1){
 90         int Mid=(Left+Right)>>1;
 91         if(Check(Mid)) Right=Mid;
 92         else           Left=Mid; 
 93     }
 94     int ans;
 95     if(Check(Right)) ans=Right;else 
 96     if(Check(Left)) ans=Left;
 97     else ans=-1; 
 98     cout<<ans<<endl; 
 99     return 0;
100 }
Codes

T2:

大水题,相当于几个小水题组合到一起。

前两个问深搜路径即可

最后一问:

不难发现对于任意位置i,它如果可以构成某个常数,

那么加数必然由两部分组成,左边来的和右边来的(记为L_i,R_i)

而显然,Ri=Li+1,Ri+1=SUM-Li+1-A[i+1]。这说明什么?

只要枚举某一项的Li,Ri,便可就出sum,依次往下推。效率:O(lim_LI*Lim_Ri*n)=O(40000*n)

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 const int N = 70;
 9 const int M = N*N;
10 #define For(i,n) for(int i=1;i<=n;i++)
11 #define Rep(i,l,r) for(int i=l;i<=r;i++)
12 
13 struct edge{
14     int s,t,w,next;
15 }E[M];
16 
17 struct way{
18     int A[N];
19 }id,q[N][N*N];
20 
21 int n,m,t,head[N],Es,ans1,cnt[N],ans2,cost[N];
22 bool vis[N];
23 void makelist(int s,int t,int w){
24     E[Es].s=s;E[Es].t=t;E[Es].w=w;
25     E[Es].next=head[s];head[s]=Es++;
26 }
27 
28 void DFS(int s,int k,int w){
29     if(k>n) return;
30     if(k>ans1) ans1=k;
31     if(k%2==0){
32         if(k>=ans2){
33             ans2=k;
34             q[ans2][++cnt[ans2]]=id;
35         }
36     }
37     for(int p=head[s];p!=-1;p=E[p].next){
38         if(!vis[E[p].t]&&w+E[p].w<=t){
39             vis[E[p].t]=true;
40             id.A[k+1]=cost[E[p].t];
41             DFS(E[p].t,k+1,w+E[p].w);
42             vis[E[p].t]=false;
43         }
44     }
45 }
46 
47 bool cmp(way A,way B){
48     int p=1;
49     while(p<=ans2){
50         if(A.A[p]<B.A[p]) return true;
51         if(A.A[p]>B.A[p]) return false;
52         p++;
53     }
54     return false;
55 }
56 
57 void Deal(){
58     Rep(l1,0,200)
59       Rep(r1,0,200){
60           int sum=id.A[1]+l1+r1;
61           int left=l1,right=r1;
62           bool flag=true;
63           Rep(i,2,ans2){
64               left=right;
65               right=sum-id.A[i]-left;
66               if(right<0){
67                   flag=false;
68                   break;
69               }
70           }
71           if(right!=l1) continue;
72           if(!flag) continue;
73           puts("Yes");
74           return;
75       }
76     puts("NO");
77 }
78 
79 int main(){
80     freopen("zroad.in","r",stdin);
81     freopen("zroad.out","w",stdout);
82     memset(head,-1,sizeof(head));
83     scanf("%d%d%d",&n,&m,&t);
84     vis[1]=true;
85     For(i,n) scanf("%d",&cost[i]);
86     For(i,m){
87         int x,y,z;
88         scanf("%d%d%d",&x,&y,&z);
89         makelist(x,y,z);
90     }id.A[1]=cost[1];
91     DFS(1,1,0);
92     cout<<ans1<<endl;
93     sort(q[ans2]+1,q[ans2]+cnt[ans2]+1,cmp);
94     id=q[ans2][1];
95     For(i,ans2) cout<<q[ans2][1].A[i]<<' ';cout<<endl;
96     Deal();
97     return 0;
98 }
Codes

 

posted @ 2014-10-31 11:14  ZJDx1998  阅读(199)  评论(2编辑  收藏  举报