Luo Gu topic - more complex graph theory I

P1268 tree weight (thinking title)

Meaning of the questions:

First, the definition of a tree on each side of the weight of several right and now to the shortest distance between you and each leaf node, so that you find the weight of the tree

Ideas:

Define the distance between the leaf node is dis [u, v]

So we will first consider the case of only two nodes, then the answer is dis [u, v]

When n = 3, we will consider the number of nodes added to the tree 3, since each node is a leaf node, then the node 3 are connected by only one edge to the connection 1 and 2

Length len = (dis (1,3) + dis (2,3) -dis (1,2)) / 2

n> 3, the case is also the same reason. Enumeration i, n is not look at point branching off from a point of the path ~ i, len is the minimum determined to be applied to the inside of the answer

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define inf 0x3f3f3f3f
 using namespace std;
 const int maxn=35;
 int dis[maxn][maxn];
 int main()
 {
     int n,x;
     while(scanf("%d",&n)&&n){
         memset(dis,0,sizeof(dis));
         for(int i=1;i<n;++i){
             for(int j=i+1;j<=n;++j){
                 scanf("%d",&x);
                 dis[i][j]=x,dis[j][i]=x;
             }
         }
        int ans=dis[1][2];
        for(int i=3;i<=n;i++){
            int len=inf;
            for(int j=1;j<i;j++){
                for(int k=1;k<j;k++)
                    len = min (len, (dis [i] [j] + dis [k] [i] -dis [k] [j]) >> 1 );
            }
            ans + = only;
        }
        cout<<ans<<endl;
     }
 }
View Code

 

P1113 chores (topological sort)

Meaning of the questions:

There are n tasks, each has its required completion time, and its predecessors have, to complete all tasks asked how long (not directly related to the task can be started at the same time)

Ideas:

Write your own a little bit more complicated

First built in map, for a mission to all of its predecessors even a directed edge (from the front even to themselves), and read into the record a point

Before traversing again, the 0-degree point is added to the queue, which all adjacent edge points into a reduced degree, if the degree of the 0-point, the addition of the queue

More crucial point is how to update dp [nex] = max (dp [nex], dp [i] + tim [nex])

My writing is more complex, with more than one queue save time, with a DP will be able to directly address the array

 

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
 using namespace std;
 const int maxn=1e5+10;
 queue<int> a,b;
 vector<int> edge[maxn];
 int in[maxn],tim[maxn],ans,n,mx[maxn];
 void solve()
 {
     for(int i=1;i<=n;i++){
         if(!in[i]){
             a.push(i),b.push(tim[i]);
         }
     }
     while(!a.empty()){
         int x=a.front(),y=b.front();
         a.pop(),b.pop();
         ans=max(ans,y);
         for(int i=0;i<edge[x].size();i++){
             in[edge[x][i]]--;
             mx[edge[x][i]]=max(y,mx[edge[x][i]]);
             if(!in[edge[x][i]]){
                 a.push(edge[x][i]);
                 b.push(tim[edge[x][i]]+mx[edge[x][i]]);
             }
         }
     }
 }
 int main ()
 {
     int x,y,temp;
     scanf("%d",&n);
     for(int i=1;i<=n;i++){
         scanf("%d%d",&x,&y);
         tim[x]=y;
         while(scanf("%d",&temp)&&temp){
             edge[temp].push_back(x);
             in[x]++;
         }
     }
     memset(mx,-inf,sizeof(mx));
     years = - inf;
     solve();
     cout<<ans<<endl;
 }
View Code

 

P1525 held criminals (bipartite graph / disjoint-set)

Meaning of the questions:

You m contradictory relationship, the relationship between each related to the respective x, y two contradictory value w

Please judge assigned to the two sets of x and y, the ability to avoid conflict

Please avoid output as 0, if the conflict is unavoidable, please smallest contradiction output value

Ideas:

Methods ①: disjoint-set

Disjoint-set can maintain connectivity, transfer resistance, layman's terms, 亲戚的亲戚是亲戚.

We might think: two people a, b grudges, so put them together will obviously be a fight, then we might as well put other enemies of a and b together,

Because of this situation may occur, "the enemy's enemy is my friend", just a no contradiction between b and other enemies, then they can be placed in the same collection, and vice a versa b.

We can not follow the relationship between weight descending order, so you can ensure the event of conflict, the answer is minimal

For added every relationship, we first determine whether they are in the same collection, if it shows in the words of conflict, direct output answer

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
 using namespace std;
 const int maxn1=2e4+10;
 const int maxn2=1e5+10;
 int fa[maxn1],ene[maxn1];
 struct node{
     int u,v,w;
 }edge[maxn2];
 int find(int x){return fa[x]==x?x:(fa[x]=find(fa[x]));}
 int cmp(node a,node b){return a.w>b.w;}
 int main()
 {
     int n,m;
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
     for(int i=1;i<=n;i++) fa[i]=i;
     memset(ene,0,sizeof(ene));
     sort(edge+1,edge+1+m,cmp);
     for(int i=1;i<=m;i++){
         int u=edge[i].u,v=edge[i].v,w=edge[i].w;
         int f1=find(u),f2=find(v);
         if(f1==f2){
             cout<<w<<endl;
             return 0;
         }
        else {
             if (! one [u]) one [u] = v;
            presence     fa [Find (s [n])] = find (V);
            if (! one [s]) one [v] = u;
            presence     fa [Find (s [t])] = find (u);
        }
     }
    cout<<0<<endl;
    return 0;
 }
View Code

Method ②: bipartite FIG.

See the inmates divided into two groups it should be easy to think of the practice of bipartite graph

It is clear that not all cases can speak for all the prisoners into two parts, there must be some conflicts can not be avoided

We can also note that the conflict is monotone, we can think of half of practice

We binary answer, provided the value of the current mid-half, two contradictory any case both x and y must be divided in two different sets, the criminals as a node, the conflict between the mid value equals an even criminal side, we get an undirected graph. At this time, we simply determined whether this undirected bipartite graph can be (due to the two parts), if it is a bipartite graph, so that the right half point R = mid, or to make L = mid

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
 using namespace std;
 const int maxn=2e5+10;
 struct edge{
     int u,v,w;
 }p[maxn];
 int n,m,L=0,R=0,cnt=0,head[maxn];
 void add_edge(int x,int y,int w)
 {
     p[++cnt].u=head[x];
     head[x]=cnt;
     p[cnt].v=y;
     p[cnt].w=w;
 }
 bool judge(int mid)
 {
     queue<int> q;
     int color[maxn]={0};
     for(int i=1;i<=n;i++){
         if(!color[i]) color[i]=1,q.push(i);
         while(!q.empty()){
             int x=q.front();
             q.pop();
             for(int j=head[x];j;j=p[j].u){
                 if(p[j].w>=mid){
                     if(!color[p[j].v]){
                         q.push(p[j].v);
                         if(color[x]==1)    color[p[j].v]=2;
                         else    color[p[j].v]=1;
                     }
                    else if(color[p[j].v]==color[x])
                        return false;
                 }
             }
         }
     }
     return true;
 }
 int main()
 {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++){
         int u,v,w;
         scanf("%d%d%d",&u,&v,&w);
         R=max(R,w);
         add_edge(u,v,w);
         add_edge(v,u,w);
     }
    int ans=0;
    R++;
    while(L+1<R){
        int mid=(L+R)>>1;
        if(judge(mid))    R=mid;
        else L=mid;
    }
    cout<<L<<endl;
    return 0;
  } 
View Code

 

Guess you like

Origin www.cnblogs.com/overrate-wsj/p/12310271.html