A:SB题。


 

B:

        X 国有 N 座城市,由 N-1 条道路连接形成了一棵树,每条边都有边权 wi 表示经过这条边需要 wi 的时间。为了方便出行,X 国计划在每座城市建造一座传送装置,它们两两之间可以进行传送。传送并不是即时的,初始时你需要给每个传送装置设置一个参数 ai,从装置 i 传送到装置 j 需要花费 |ai aj | 的时间。

        X 国并不希望得不偿失的情况发生,因此不能有任意两个城市之间通过传送需要的时间超过走路时间。同时,由于传送装置受每个城市的地质情况限制,每个城市的传送装置参数 ai 只能是区间 [li, ri] 之内。当然你也可以对城市的地质进行改造,花费 x的代价可以使所有城市能接受的参数区间扩大为 [li x, ri + x]。代价必须是一个非负整数。

        问在不进行改造的情况下,能否找到一种安排 ai 的方案,满足上述所有要求。有时你还需要回答在允许进行改造的情况下,最少花费多少代价进行改造,可以找到一种方案满足要求 (如果不需要改造就可满足则输出 0)。

        要求线性。

差分约束,发现负环大大小即为max(0,min(dis(i,j)-li+ri))。

  1 #pragma GCC optimize 2
  2 #include<bits/stdc++.h>
  3 using namespace std;
  4 typedef long long int ll;
  5 const int maxn=1E6+5;
  6 const int base=1000002;
  7 const ll inf=1E16;
  8 int n,type,A[maxn],B[maxn],C[maxn];
  9 int size,head[maxn],cnt[maxn],Q[maxn];
 10 bool vis[maxn];
 11 ll ans,dep[maxn],l[maxn],r[maxn],fA[maxn],fB[maxn];
 12 inline int read()
 13 {
 14     char ch=getchar();
 15     bool flag=0;
 16     if(ch=='-')flag=1;
 17     while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=1;}
 18     int sum=ch-'0';
 19     ch=getchar();
 20     while(isdigit(ch)){sum=sum*10+ch-'0';ch=getchar();}
 21     if(flag)
 22         return -sum;
 23     return sum;
 24 }
 25 int G[55];
 26 inline void write(ll x)
 27 {
 28     int tot=0;
 29     do{G[++tot]=x%10;x/=10;}while(x);
 30     for(int i=tot;i>=1;--i)putchar('0'+G[i]);
 31     putchar('\n');
 32 }
 33 struct edge
 34 {
 35     int to,next,w;
 36 }E[maxn*4];
 37 inline void add(int u,int v,int w)
 38 {
 39     E[++size].to=v;
 40     E[size].next=head[u];
 41     E[size].w=w;
 42     head[u]=size;
 43 }
 44 inline void clear()
 45 {
 46     memset(head,0,sizeof(head));
 47     memset(E,0,sizeof(E));
 48     size=0;
 49 }
 50 void dfs(int u,int F,ll d)
 51 {
 52     dep[u]=d;
 53     fA[u]=fB[u]=inf;
 54     for(int i=head[u];i;i=E[i].next)
 55     {
 56         int v=E[i].to;
 57         if(v==F)
 58             continue;
 59         dfs(v,u,d+E[i].w);
 60         fA[u]=min(fA[u],fA[v]);
 61         fB[u]=min(fB[u],fB[v]);
 62     }
 63     fA[u]=min(fA[u],dep[u]-l[u]);
 64     fB[u]=min(fB[u],dep[u]+r[u]);
 65     ans=min(ans,fA[u]+fB[u]-(ll)2*dep[u]);
 66 }
 67 inline ll get()
 68 {
 69     clear();
 70     for(int i=1;i<=n-1;++i)
 71     {
 72         add(A[i],B[i],C[i]);
 73         add(B[i],A[i],C[i]);
 74     }
 75     ans=inf;
 76     dfs(1,1,0);
 77     return ans;
 78 }
 79 inline void solve()
 80 {
 81     n=read();
 82     for(int i=1;i<=n;++i)
 83         l[i]=read();
 84     for(int i=1;i<=n;++i)
 85         r[i]=read();
 86     for(int i=1;i<=n-1;++i)
 87         A[i]=read(),B[i]=read(),C[i]=read();
 88     ll x=get();
 89     if(type==0)
 90     {
 91         if(x>=0)
 92             write(0);
 93         else
 94             write(1);
 95     }
 96     else
 97         write(max((ll)0,(-ans+(ll)1)/(ll)2));
 98 }
 99 int main()
100 {
101 //    freopen("teleport.in","r",stdin);
102 //    freopen("teleport.out","w",stdout);
103     ios::sync_with_stdio(false);
104     int T=read();
105     type=read();
106     while(T--)
107         solve();
108     return 0;
109 }
View Code

C:n个点,m条边的无向图,每条边有颜色R或G或B,问有多少棵G颜色边小于等于x、B颜色边小于等于y的生成树。n<=40

将矩阵树定理中的数字换为字母,我们就相当于求一个多项式中x次方、y次方小于等于给定条件的系数和。用二维拉格朗日插值,展开多项式即可。复杂度O(n6),要卡常。

$f(x,y)=\sum_{i,j}{f(i,j)\prod_{k≠i}{\frac{x-x_k}{x_i-x_k}}\prod_{k≠j}{\frac{y-y_k}{y_j-y_k}}}$

  1 #define mod 1000000007
  2 #include<bits/stdc++.h>
  3 using namespace std;
  4 typedef long long int ll;
  5 int n,m,L1,L2;
  6 int R[55][55],G[55][55],B[55][55];
  7 inline ll qpow(ll x,ll y)
  8 {
  9     ll ans=1,base=x;
 10     while(y)
 11     {
 12         if(y&1)
 13             ans=ans*base%mod;
 14         base=base*base%mod;
 15         y>>=1; 
 16     }
 17     return ans;
 18 }
 19 inline void add(ll&x,ll y)
 20 {
 21     x=(x+y)%mod;
 22 }
 23 struct matrix
 24 {
 25     ll a[55][55],m;
 26     matrix()
 27     {
 28         memset(a,0,sizeof(a));
 29     }
 30     inline void addTo(int x1,int x2,ll c)
 31     {
 32         for(int i=1;i<=m;++i)
 33             a[x1][i]=(((a[x1][i]+a[x2][i]*c)%mod+mod)%mod);
 34     }
 35     inline ll get()
 36     {
 37         for(int i=1;i<=m;++i)
 38             for(int j=i+1;j<=m;++j)
 39             {
 40                 ll d=(-a[j][i]*qpow(a[i][i],mod-2)%mod+mod)%mod;
 41                 addTo(j,i,d);
 42             }
 43         ll sum=1;
 44         for(int i=1;i<=m;++i)
 45             sum=sum*a[i][i]%mod;
 46         return (sum+mod)%mod;
 47     }
 48 };
 49 int TOT;
 50 struct Poly
 51 {
 52     int len1,len2;
 53     ll a[55][55];
 54     Poly()
 55     {
 56         len1=len2=0;
 57     }
 58     inline Poly operator*(const ll&d)
 59     {
 60         Poly B; 
 61         for(int i=0;i<=len1;++i)
 62             for(int j=0;j<=len2;++j)
 63                 B.a[i][j]=a[i][j]*d%mod;
 64         B.len1=len1,B.len2=len2;
 65         return B;
 66     }
 67     Poly operator*(const Poly&A)
 68     {
 69         Poly B;
 70         for(int i=0;i<=len1+A.len1;++i)
 71             for(int j=0;j<=len2+A.len2;++j)
 72                 B.a[i][j]=0;
 73         for(int i1=0;i1<=len1;++i1)
 74         for(int j1=0;j1<=len2;++j1)
 75         for(int i2=0;i2<=A.len1;++i2)
 76         for(int j2=0;j2<=A.len2;++j2)
 77             add(B.a[i1+i2][j1+j2],a[i1][j1]*A.a[i2][j2]%mod);
 78         B.len1=len1+A.len1,B.len2=len2+A.len2;
 79         return B;
 80     }
 81     Poly operator+(const Poly&A)
 82     {
 83         Poly B;
 84         for(int i=0;i<=max(len1,A.len1);++i)
 85             for(int j=0;j<=max(len2,A.len2);++j)
 86                 B.a[i][j]=(a[i][j]+A.a[i][j])%mod;
 87         B.len1=max(len1,A.len1),B.len2=max(len2,A.len2);
 88         return B;
 89     }
 90     inline void out()
 91     {
 92         for(int i=0;i<=n;++i,cout<<endl)
 93             for(int j=0;j<=n;++j)
 94                 cout<<a[i][j]<<" ";
 95     }
 96 };
 97 ll f[55][55];
 98 bool visA[55],visB[55];
 99 Poly hA[55],hB[55];
100 inline void solve() 
101 {
102     for(int x=1;x<=n;++x)
103         for(int y=1;y<=n;++y)
104         {
105             matrix M;
106             M.m=n-1;
107             for(int i=1;i<=n;++i)
108                 for(int j=1;j<=n;++j)
109                 {
110                     M.a[i][i]+=R[i][j]+G[i][j]*x+B[i][j]*y;
111                     M.a[i][j]-=R[i][j]+G[i][j]*x+B[i][j]*y;
112                 }
113             f[x][y]=M.get();
114         }
115     Poly ans;
116     for(int i=1;i<=n;++i)
117         for(int j=1;j<=n;++j)
118         {
119             Poly now;
120             now.a[0][0]=1;
121             if(!visA[i])
122             {
123                 ll s=1;
124                 Poly B;
125                 B.a[0][0]=1;
126                 for(int k=1;k<=n;++k)
127                 {
128                     if(i==k)
129                         continue;
130                     Poly A;
131                     A.a[0][0]=mod-k;
132                     A.a[1][0]=1;
133                     A.len1=1;
134                     s=s*(i-k+mod)%mod;
135                     B=B*A;
136                 }
137                 s=qpow(s,mod-2);
138                 hA[i]=B*s;
139                 visA[i]=1;
140             }
141             now=now*hA[i];
142             if(!visB[j])
143             {
144                 ll s=1;
145                 Poly B;
146                 B.a[0][0]=1;
147                 for(int k=1;k<=n;++k)
148                 {
149                     if(j==k)
150                         continue;
151                     Poly A;
152                     A.a[0][0]=mod-k;
153                     A.a[0][1]=1;
154                     A.len2=1;
155                     s=s*(j-k+mod)%mod;
156                     B=B*A;
157                 }
158                 s=qpow(s,mod-2);
159                 hB[j]=B*s;
160                 visB[j]=1;
161             }
162             now=now*hB[j];
163             now=now*f[i][j];
164             ans=ans+now;
165         }
166     ll sum=0;
167     for(int i=0;i<=L1;++i)
168         for(int j=0;j<=L2;++j)
169             add(sum,ans.a[i][j]);
170     cout<<sum<<endl;
171 }
172 int main()
173 {
174 //    freopen("tree.in","w",stdout);
175 //    freopen("tree.out","w",stdout);
176     ios::sync_with_stdio(false);
177     cin>>n>>m>>L1>>L2;
178     L1=min(L1,n-1),L2=min(L2,n-1);
179     for(int i=1;i<=m;++i)
180     {
181         int x,y,c;
182         cin>>x>>y>>c;
183         if(x==y)
184             continue;
185         if(c==1)
186             ++R[x][y],++R[y][x];
187         else if(c==2)
188             ++G[x][y],++G[y][x];
189         else
190             ++B[x][y],++B[y][x];
191     }
192     solve();
193     return 0;
194 }
View Code

 

 posted on 2020-02-10 14:13  GreenDuck  阅读(212)  评论(0编辑  收藏  举报