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(' '); 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 }
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 }