乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      算法競賽入門經(jīng)典 寫題筆記(第五章 圖論算法與模型2)

       印度阿三17 2019-05-12

      本節(jié)內(nèi)容——

      • 2-SAT

      • dijstra算法的一些應用

      • SPFA算法的一些應用


      例題9 飛機調(diào)度

      有n架飛機需要著陸。每架飛機都可以選擇“早著陸"和”晚著陸“兩種方式之一,且必須選擇一種。第i架飛機的早著陸時間為\(E_i\),晚著陸時間為\(L_I\),不得在其他時間著陸。現(xiàn)在需要安排這些飛機的著陸方式,使得整個著陸計劃盡量安全。換句話說,如果把所有飛機的實際著陸時間按照從早到晚的順序排列,相鄰兩個著陸時間間隔的最小值(成為安全間隔)盡量大。

      也就是二分這個時間,然后判斷該2-SAT是否有解。(因為這個間隔時間越小就也可能有合法解,反之越不可能,所以可以二分答案)
      構圖的時候,如果兩個決策(比如說\(i_l,j_l\))間隔小于二分的答案,我們就給\(i_l,j_r\)和\(i_r,j_l\)連有向邊。
      然后跑tarjan判斷就行了,如果同一個飛機的兩個決策在一個強聯(lián)通分量里面,就沒有合法解了。
      順便一提,劉汝佳書上寫的那個做法復雜度是假的qwq

      #include<iostream>
      #include<cstdio>
      #include<cstring>
      #include<algorithm>
      #include<cmath>
      #define MAXN 4010
      #define INF 0x3f3f3f3f
      using namespace std;
      int n,m,t,tot,cnt,top;
      int head[MAXN],dfn[MAXN],low[MAXN],in[MAXN],st[MAXN],c[MAXN];
      struct Edge{int nxt,to;}edge[MAXN*MAXN];
      struct Node{int l,r;}node[MAXN];
      inline void add(int from,int to){edge[  t].nxt=head[from],edge[t].to=to,head[from]=t;}
      inline void tarjan(int x)
      {
          dfn[x]=low[x]=  tot;
          in[x]=1;
          st[  top]=x;
          for(int i=head[x];i;i=edge[i].nxt)
          {
              int v=edge[i].to;
              if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);
              else if(in[v]) low[x]=min(low[x],dfn[v]);
          }
          if(dfn[x]==low[x])
          {
              int v;  cnt;
              do{v=st[top--],c[v]=cnt,in[v]=0;}while(x!=v);
          }
      }
      inline bool check(int x)
      {
          memset(head,0,sizeof(head));
          t=tot=top=cnt=0;
          for(int i=1;i<=(n>>1);i  )
              for(int j=1;j<=(n>>1);j  )
              {
                  if(i==j) continue;
                  int a=abs(node[i].l-node[j].l);
                  int b=abs(node[i].l-node[j].r);
                  int c=abs(node[i].r-node[j].l);
                  int d=abs(node[i].r-node[j].r);
                  if(a<x) add(i*2-1,j*2);
                  if(b<x) add(i*2-1,j*2-1);
                  if(c<x) add(i*2,j*2);
                  if(d<x) add(i*2,j*2-1);
              }
          memset(low,0,sizeof(low));
          memset(dfn,0,sizeof(dfn));
          memset(in,0,sizeof(in));
          for(int i=1;i<=n;i  )
              if(!dfn[i])
                  tarjan(i);
          for(int i=1;i<n;i =2)
              if(c[i]==c[i 1])
                  return false;
          return true;
      }
      int main()
      {
          #ifndef ONLINE_JUDGE
          freopen("ce.in","r",stdin);
          #endif
          while(scanf("%d",&n)!=EOF)
          {
              for(int i=1;i<=n;i  ) scanf("%d%d",&node[i].l,&node[i].r);
              n<<=1;
              int l=0,r=INF,ans=0;
              while(l<=r)
              {
                  int mid=(l r)>>1;
                  if(check(mid)) ans=mid,l=mid 1;
                  else r=mid-1;
              }
              printf("%d\n",ans);
          }
          return 0;
      }

      例題10 宇航員分組

      有A,B,C三種任務要分配給n個宇航員,其中每個宇航員恰好要分配一個任務。設所有n個宇航員的平均年齡為x,只有年齡大于或等于x的宇航員才能分配任務A;只有年齡嚴格小于x的宇航員才能分配任務B,而任務C沒有限制。有m對宇航員相互討厭,因此不能分配到統(tǒng)一任務?,F(xiàn)在需要找出一個滿足上訴所有要求的任務分配方案。

      3-SAT???不可能的。我們只要處理一下年齡,對于每個宇航員,照樣是2-SAT.
      然后就......和上面那題一樣做就行了????
      但是為什么會RE啊......搞不懂......先把代碼貼上,回來找鍋(咕咕咕)

      #include<iostream>
      #include<cstdio>
      #include<algorithm>
      #include<cstring>
      #include<cmath>
      #define MAXN 100010
      using namespace std;
      int n,m,all,kkk,cnt,tot,top,t;
      int head[MAXN],done[MAXN];
      int dfn[MAXN],low[MAXN],in[MAXN],st[MAXN],c[MAXN];
      char op[MAXN];
      struct Node{int l,r,age;}node[MAXN];
      struct Edge{int nxt,to;}edge[MAXN<<1];
      struct Line{int u,v;}line[MAXN<<1];
      inline void add(int from,int to){edge[  t].nxt=head[from],edge[t].to=to,head[from]=t;}
      inline void tarjan(int x)
      {
          low[x]=dfn[x]=  tot;
          for(int i=head[x];i;i=edge[i].nxt)
          {
              int v=edge[i].to;
              if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);
              else if(in[v]) low[x]=min(low[x],dfn[v]);
          }
          if(low[x]==dfn[x])
          {
              int v;  cnt;
              do{v=st[top--];in[v]=0;c[v]=  cnt;}while(x!=v);
          }
      }
      inline bool check()
      {
          memset(head,0,sizeof(head));
          memset(in,0,sizeof(in));
          memset(dfn,0,sizeof(dfn));
          memset(low,0,sizeof(low));
          top=tot=t=cnt=0;
          for(int i=1;i<=m;i  )
          {
              int u=line[i].u,v=line[i].v;
              if(node[u].age^node[v].age) 
              {
                  add(node[u].r,node[v].l),printf("%d %d\n",node[u].r,node[v].l);
                  add(node[v].r,node[u].l),printf("%d %d\n",node[v].r,node[u].l);
              }
              else
              {
                  add(node[u].l,node[v].r),printf("%d %d\n",node[u].l,node[v].r);
                  add(node[u].r,node[v].l),printf("%d %d\n",node[u].r,node[v].l);
                  add(node[v].l,node[u].r),printf("%d %d\n",node[v].l,node[u].r);
                  add(node[v].r,node[u].l),printf("%d %d\n",node[v].r,node[u].l);
              }
          }
          for(int i=1;i<=n;i  )
              if(!dfn[i])
                  tarjan(i),cout<<i<<endl;
          for(int i=1;i<=n;i  )
              if(c[node[i].l]==c[node[i].r]&&c[node[i].l]!=0)
                  return false;
          return true;
      }
      inline bool solve(int x,int c)
      {
          done[x]=c,done[x^1]=3-c;
          printf("done[%d]=%d done[%d]=%d\n",x,done[x],x^1,done[x^1]);
          cout<<endl;
          for(int i=head[x];i;i=edge[i].nxt)
          {
              int v=edge[i].to;
              if(done[v]&&done[v]==c) return false; 
              else if(!done[v]) solve(v,c);
          }
          return true;
      }
      inline void print()
      {
          cout<<"yes"<<endl;
          for(int i=1;i<=n;i  )
          {
              if(done[node[i].l]==1) printf("%c\n",op[node[i].l]);
              else if(done[node[i].l]==0&&done[node[i].r]==0) printf("%c\n",op[node[i].l]);
          }
      }
      int main()
      {
          #ifndef ONLINE_JUDGE
          freopen("ce.in","r",stdin);
          #endif
          while(scanf("%d%d",&n,&m)==2)
          {
              if(n==0&&m==0) break;
              memset(head,0,sizeof(head));
              top=tot=t=cnt=all=0;
              for(int i=1;i<=n;i  ) scanf("%d",&node[i].age),all =node[i].age;
              all/=n;
              for(int i=1;i<=n;i  )
              {
                  if(node[i].age<all) node[i].age=0;
                  else node[i].age=1;
              }
              for(int i=1;i<=n;i  ) scanf("%d%d",&line[i].u,&line[i].v);
              for(int i=1;i<=n;i  ) 
                  if(node[i].age==0) 
                      node[i].l=  kkk,op[kkk]='B',node[i].r=  kkk,op[kkk]='C';
                  else 
                      node[i].l=  kkk,op[kkk]='A',node[i].r=  kkk,op[kkk]='C';
              for(int i=1;i<=n;i  )
                  printf("%c %c\n",op[node[i].l],op[node[i].r]);
              if(check()==false) {printf("No solution.\n");continue;}
              memset(done,0,sizeof(done));
              bool flag=true;
              for(int i=1;i<=n;i  )
                  if(!done[i])
                      if(solve(node[i].l,1))
                          flag=false;
              if(flag==true) {print();continue;}
              memset(done,0,sizeof(done));
              flag=true;
              for(int i=1;i<=n;i  )
                  if(!done[i])
                      solve(node[i].r,1);
              print();
          }
          return 0;
      }

      例題11 機場快線

      機場快線分為經(jīng)濟線和商業(yè)線兩種,線路、速度和價錢都不同?,F(xiàn)在你有一張商業(yè)線的車票,可以坐一站商業(yè)線,而其他時候只能乘坐經(jīng)濟線。假設換成時間忽略不計,你的任務是找一條取機場最快的線路,然后輸出方案。(保證最優(yōu)解唯一)

      因為商業(yè)線只能坐一站,而且數(shù)據(jù)范圍在1000以內(nèi),所以我們可以枚舉坐的是哪一站。
      假設我們用商業(yè)線車票從車站a坐到b,則從起點到a,從b到終點這兩部分的路線對于只存在經(jīng)濟線的圖中一定是最短路。所以我們只需要從起點、終點開始做兩次最短路,記錄下從起點到每個點x的最短時間\(f(x)\)和它到終點的最短時間\(g(x)\),那么總時間就是\(f(a) time(a,b) g(b)\)。

      #include<cstdio>
      #include<cstring>
      #include<algorithm>
      #include<iostream>
      #include<string>
      #include<vector>
      #include<stack>
      #include<bitset>
      #include<cstdlib>
      #include<cmath>
      #include<set>
      #include<list>
      #include<deque>
      #include<map>
      #include<queue>
      #define Max(a,b) ((a)>(b)?(a):(b))
      #define Min(a,b) ((a)<(b)?(a):(b))
      using namespace std;
      typedef long long ll;
      const double PI = acos(-1.0);
      const double eps = 1e-6;
      const int mod = 1000000000   7;
      const int INF = 1000000000;
      const int maxn = 500   10;
      int T,n,m,S,d1[maxn], p1[maxn], d2[maxn], p2[maxn], vis[maxn], ok, dist;
      struct node {
          int u, val;
          node(int u=0, int val=0):u(u), val(val) {}
          bool operator < (const node& rhs) const {
              return val > rhs.val;
          }
      };
      void print(int root, int p[], int id, int S) {
          vector<int> ans;
          while(root != S) {
              ans.push_back(root);
              root = p[root];
          }
          ans.push_back(root);
          int len = ans.size();
       
          if(id == 1) for(int i=len-1;i>=0;i--) {
              if(i != len-1) printf(" ");
              printf("%d",ans[i]);
          }
          else for(int i=0;i<len;i  ) {
              if(i != 0) printf(" ");
              printf("%d",ans[i]);
          }
      }
      vector<node> g[maxn];
      void BFS(int haha, int d[], int p[]) {
          priority_queue<node> q;
          q.push(node(haha, 0));
          for(int i=1;i<=n;i  ) {
              d[i] = INF;
          }
          d[haha] = 0;
          memset(vis, false, sizeof(vis));
          while(!q.empty()) {
              node u = q.top(); q.pop();
              if(vis[u.u]) continue;
              vis[u.u] = true;
              int len = g[u.u].size();
              for(int i=0;i<len;i  ) {
                  node v = g[u.u][i];
                  if(d[v.u] > d[u.u]   v.val) {
                      d[v.u] = d[u.u]   v.val;
                      p[v.u] = u.u;
                      q.push(node(v.u, d[v.u]));
                  }
              }
          }
      }
      int a,b,c,kase=0;
      int main() {
          #ifndef ONLINE_JUDGE
          freopen("ce.in","r",stdin);
          #endif
          while(~scanf("%d%d%d",&n,&S,&T)) {
              scanf("%d",&m);
              for(int i=1;i<=n;i  ) g[i].clear();
              while(m--) {
                  scanf("%d%d%d",&a,&b,&c);
                  g[a].push_back(node(b, c));
                  g[b].push_back(node(a, c));
              }
              scanf("%d",&m);
              ok = -1;
              BFS(S, d1, p1);
              BFS(T, d2, p2);
              int s = -1,t = -1,ans = d1[T], res = 0;
              for(int i=0;i<m;i  ) {
                  scanf("%d%d%d",&a,&b,&c);
                  if(cur < ans) {
                      ans = cur;
                      s = b; t = a;
                  }
              }
              if(kase) printf("\n");
              else   kase;
              if(s > 0) {
                  print(s, p1, 1, S); printf(" ");
                  print(t, p2, 2, T); printf("\n");
                  printf("%d\n",s);
              }
              else {
                  print(T, p1, 1, S); printf("\n");
                  printf("Ticket Not Used\n");
              }
              printf("%d\n",ans);
          }
          return 0;
      }

      書上還提到了dij算法的路徑統(tǒng)計,在這里就簡單說一下吧
      枚舉兩點之間的所有最短路:先求出所有點到目標點的最短路長度\(d[i]\),然后從起點開始出發(fā),只沿著\(d[i]=d[j] dist(i,j)\)的邊走。
      兩點之間的最短路計數(shù):令\(f[i]\)表示從i到目標點的最短路的條數(shù),則\(f[i]=\sum f[j] | d[i]=d[j] dist(i,j)\)(這里書上寫錯了)

      例題12 林中漫步

      對于一張圖,只沿著滿足如下條件的道路(A,B)走:存在一條從B出發(fā)回家的路徑,比所有從A出發(fā)回家的路徑都短。問不同的回家路徑條數(shù)。

      先跑完以家為源點的最短路,然后如果一個點a的最短路比b的小,那么連邊,這就是一個DAG了,然后再DP計個數(shù)就行了。

      #include<iostream>
      #include<cstring>
      #include<cstdio>
      #include<algorithm>
      #include<cmath>
      #include<queue>
      #define MAXN 100010
      using namespace std;
      int n,m,t;
      int head[MAXN<<1],done[MAXN],dis[MAXN],dp[MAXN];
      struct Node
      {   
          int u,d;
          friend bool operator < (Node x,Node y)
          {return x.d>y.d;}
      };
      struct Edge{int nxt,to,dis;}edge[MAXN<<1];
      struct Line{int u,v,w;}line[MAXN<<1];
      inline void add(int from,int to,int dis)
      {
          edge[  t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
      }
      inline void dij(int x)
      {
          priority_queue<Node>q;
          memset(done,0,sizeof(done));
          memset(dis,0x3f,sizeof(dis));
          q.push((Node){x,0});
          dis[x]=0;
          while(!q.empty())
          {
              int u=q.top().u;q.pop();
              if(done[u]) continue;
              done[u]=1;
              for(int i=head[u];i;i=edge[i].nxt)
              {
                  int v=edge[i].to;
                  if(dis[v]>dis[u] edge[i].dis)
                      dis[v]=dis[u] edge[i].dis,q.push((Node){v,dis[v]});
              }
          }
      }
      inline int solve(int x)
      {
          if(x==2) return dp[x]=1;
          int cur_ans=0;
          for(int i=head[x];i;i=edge[i].nxt)
          {
              int v=edge[i].to;
              if(!dp[v]) dp[v]=solve(v);
              cur_ans =dp[v];
          }
          return cur_ans;
      }
      int main()
      {
          #ifndef ONLINE_JUDGE
          freopen("ce.in","r",stdin);
          #endif
          while(scanf("%d%d",&n,&m)==2&&n)
          {
              memset(head,0,sizeof(head));
              memset(dp,0,sizeof(dp));
              t=0;
              for(int i=1;i<=m;i  )
              {
                  scanf("%d%d%d",&line[i].u,&line[i].v,&line[i].w);
                  add(line[i].u,line[i].v,line[i].w);
                  add(line[i].v,line[i].u,line[i].w);
              }
              dij(2);
              // for(int i=1;i<=n;i  ) printf("dis[%d]=%d\n",i,dis[i]);
              memset(head,0,sizeof(head));
              t=0;
              for(int i=1;i<=m;i  )
              {
                  if(dis[line[i].u]>dis[line[i].v]) add(line[i].u,line[i].v,line[i].w);
                  if(dis[line[i].v]>dis[line[i].u]) add(line[i].v,line[i].u,line[i].w);
              }
              printf("%d\n",solve(1));
          }
          return 0;
      }

      最短路樹:用dij算法可以求出單元最短路樹,方法是在發(fā)現(xiàn)\(d[i] w(i,j)<d[j]\)時除了更新\(d[j]\)之外還要設置\(p[j]=i\)。這樣,所有點就形成了一棵樹。
      要從起點出發(fā)沿著最短路走到其他任意點,只需要順著樹上的邊走即可。

      例題13 戰(zhàn)爭和物流

      給出一個n個節(jié)點m條邊的無向圖,

      例題14 過路費(加強版)

      例題15 在環(huán)中

      例題16 Halum操作

      來源:http://www./content-1-187401.html

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多