Andrew Stankevich Contest 2 (ASC 2) |我为什么要开这套题

来源:互联网 发布:26岁出国读研 知乎 编辑:程序博客网 时间:2024/06/01 09:51

F Roads

某个国家有石头路和烂泥路,石头路恰好是生成树,维护路自然是花钱的,现在希望通过修改路的维护费用使得石头路是最小生成树(可以不是唯一的MST),目标是总的修改量最小,要求输出方案。

设石头路的修改后权值为w[i]-d[i]
烂泥路的修改后权值为w[i]+d[i]
对于1条烂泥路x,恰对应了MST中一条链,显然它权值要大于上面的任意一条边y。
wx+dxwydy
dx+dywywx
原问题变为2分图最小权覆盖(Minimum Weighted Cover)
这可以用KM解决。

#include<bits/stdc++.h> using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define ForkD(i,k,n) for(int i=n;i>=k;i--)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (o<<1)#define Rson ((o<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,0x3f,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define MEMx(a,b) memset(a,b,sizeof(a));#define INF (0x3f3f3f3f)#define F (1000000007)#define pb push_back#define mp make_pair#define fi first#define se second#define vi vector<int> #define pi pair<int,int>#define SI(a) ((a).size())#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;#define PRi2D(a,n,m) For(i,n) { \                        For(j,m-1) cout<<a[i][j]<<' ';\                        cout<<a[i][m]<<endl; \                        } #pragma comment(linker, "/STACK:102400000,102400000")#define ALL(x) (x).begin(),(x).end()#define gmax(a,b) a=max(a,b);#define gmin(a,b) a=min(a,b);typedef long long ll;typedef long double ld;typedef unsigned long long ull;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return ((a-b)%F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}inline int read(){    int x=0,f=1; char ch=getchar();    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}    return x*f;} #define MAXN 500int fa[MAXN],wfa[MAXN],idefa[MAXN];vi e[MAXN],wei[MAXN],id[MAXN];int dep[MAXN]; void dfs(int x,int f,int d) {    fa[x]=f;    dep[x]=d;    Rep(i,SI(e[x])) {        int v=e[x][i],w=wei[x][i],idd=id[x][i];        if (v^f){            wfa[v]=w;            idefa[v]=idd;            dfs(v,x,d+1);        }    }}int f[MAXN][MAXN];int u[MAXN],v[MAXN],w[MAXN];namespace KM{    const int N=405;    const ll inf=~0U>>1;    int n,nl,nr,m,z,py,x,y,i,j,p,lk[N],pre[N];    bool vy[N];    int lx[N],ly[N],d,w[N][N],slk[N];ll ans;    int work(int nl,int nr){ // nl nr w      n=max(nl,nr);      For(i,nl) For(j,nr) w[i][j]=max(0,f[i][j]);//    while(m--)scanf("%d%d%d",&x,&y,&z),w[y][x]=max(w[y][x],z);      for(i=1;i<=n;i++)for(j=1;j<=n;j++)lx[i]=max(lx[i],w[i][j]);      for(i=1;i<=n;i++){        for(j=1;j<=n;j++)slk[j]=inf,vy[j]=0;        for(lk[py=0]=i;lk[py];py=p){          vy[py]=1;d=inf;x=lk[py];          for(y=1;y<=n;y++)if(!vy[y]){            if(lx[x]+ly[y]-w[x][y]<slk[y])slk[y]=lx[x]+ly[y]-w[x][y],pre[y]=py;            if(slk[y]<d)d=slk[y],p=y;          }          for(y=0;y<=n;y++)if(vy[y])lx[lk[y]]-=d,ly[y]+=d;else slk[y]-=d;        }        for(;py;py=pre[py])lk[py]=lk[pre[py]];      }      for(i=1;i<=n;i++)ans+=lx[i]+ly[i];//    printf("%lld\n",ans);//    for(i=1;i<=nl;i++)printf("%d ",w[lk[i]][i]?lk[i]:0);    }}int n,m;void prekm(int x,int y,int p) {    if (dep[x]<dep[y]) swap(x,y);    while(dep[x]>dep[y]) {        f[idefa[x]][p]=-w[p+n-1]+wfa[x];        x=fa[x];    }    while(x^y) {        f[idefa[x]][p]=-w[p+n-1]+wfa[x];        f[idefa[y]][p]=-w[p+n-1]+wfa[y];        x=fa[x];        y=fa[y];    }}int main(){    freopen("roads.in","r",stdin);    freopen("roads.out","w",stdout);    n=read(),m=read();    For(i,n-1) {        int u=read(),v=read(),w=read();        e[u].pb(v);e[v].pb(u);        wei[u].pb(w);wei[v].pb(w);        id[u].pb(i); id[v].pb(i);        ::w[i]=w;::u[i]=u;::v[i]=v;    }    dfs(1,0,1);    MEM(f)    Fork(i,n,m) {        u[i]=read(),v[i]=read();w[i]=read();        prekm(u[i],v[i],i-n+1);    }    KM::work(n-1,m-n+1);    For(i,n-1) {        printf("%d\n",w[i]-KM::lx[i]);    }    Fork(i,n,m) {        printf("%d\n",w[i]+KM::ly[i-n+1]);    }    return 0;}

H

一张票有N*M的黑白格子,可以卷成圆柱(cylinder)再卷成环,问这样操作后依然不同构的票有多少种。(n,m<=20)

根据伯恩赛德定理,等价类个数=置换集合中的每个置换不动点个数C(f)的平均值.
当n!=m时,有左移,上移,转180度,3种置换(互不影响)。
等价类个数=2nm
这题n=m时,还可以旋转90度。
等价类个数=4nm

#include<bits/stdc++.h> using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define ForkD(i,k,n) for(int i=n;i>=k;i--)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (o<<1)#define Rson ((o<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,0x3f,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define MEMx(a,b) memset(a,b,sizeof(a));#define INF (0x3f3f3f3f)#define F (1000000007)#define pb push_back#define mp make_pair#define fi first#define se second#define vi vector<int> #define pi pair<int,int>#define SI(a) ((a).size())#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);#define PRi(a,n) Rep(i,n-1) cout<<a[i]<<' '; cout<<a[n-1]<<endl;#define PRi2D(a,n,m) For(i,n) { \                        For(j,m-1) cout<<a[i][j]<<' ';\                        cout<<a[i][m]<<endl; \                        } #pragma comment(linker, "/STACK:102400000,102400000")#define ALL(x) (x).begin(),(x).end()#define gmax(a,b) a=max(a,b);#define gmin(a,b) a=min(a,b);typedef long long ll;typedef long double ld;typedef unsigned long long ull;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return ((a-b)%F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}inline int read(){    int x=0,f=1; char ch=getchar();    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}    return x*f;} int gcd(int a,int b){    return (!b)?a:gcd(b,a%b);}struct BigInteger {    typedef unsigned long long LL;    static const int BASE = 100000000;    static const int WIDTH = 8;    vector<int> s;    BigInteger& clean(){while(!s.back()&&s.size()>1)s.pop_back(); return *this;}    BigInteger(LL num = 0) {*this = num;}    BigInteger(string s) {*this = s;}    BigInteger& operator = (long long num) {        s.clear();        do {            s.push_back(num % BASE);            num /= BASE;        } while (num > 0);        return *this;    }    BigInteger& operator = (const string& str) {        s.clear();        int x, len = (str.length() - 1) / WIDTH + 1;        for (int i = 0; i < len; i++) {            int end = str.length() - i*WIDTH;            int start = max(0, end - WIDTH);            sscanf(str.substr(start,end-start).c_str(), "%d", &x);            s.push_back(x);        }        return (*this).clean();    }    BigInteger operator + (const BigInteger& b) const {        BigInteger c; c.s.clear();        for (int i = 0, g = 0; ; i++) {            if (g == 0 && i >= s.size() && i >= b.s.size()) break;            int x = g;            if (i < s.size()) x += s[i];            if (i < b.s.size()) x += b.s[i];            c.s.push_back(x % BASE);            g = x / BASE;        }        return c;    }    BigInteger operator - (const BigInteger& b) const {        assert(b <= *this); // ¼õÊý²»ÄÜ´óÓÚ±»¼õÊý        BigInteger c; c.s.clear();        for (int i = 0, g = 0; ; i++) {            if (g == 0 && i >= s.size() && i >= b.s.size()) break;            int x = s[i] + g;            if (i < b.s.size()) x -= b.s[i];            if (x < 0) {g = -1; x += BASE;} else g = 0;            c.s.push_back(x);        }        return c.clean();    }    BigInteger operator * (const BigInteger& b) const {        int i, j; LL g;        vector<LL> v(s.size()+b.s.size(), 0);        BigInteger c; c.s.clear();        for(i=0;i<s.size();i++) for(j=0;j<b.s.size();j++) v[i+j]+=LL(s[i])*b.s[j];        for (i = 0, g = 0; ; i++) {            if (g ==0 && i >= v.size()) break;            LL x = v[i] + g;            c.s.push_back(x % BASE);            g = x / BASE;        }        return c.clean();    }    BigInteger operator / (const BigInteger& b) const {        assert(b > 0);  // ³ýÊý±ØÐë´óÓÚ0        BigInteger c = *this;       // ÉÌ:Ö÷ÒªÊÇÈÃc.sºÍ(*this).sµÄvectorÒ»Ñù´ó        BigInteger m;               // ÓàÊý:³õʼ»¯Îª0        for (int i = s.size()-1; i >= 0; i--) {            m = m*BASE + s[i];            c.s[i] = bsearch(b, m);            m -= b*c.s[i];        }        return c.clean();    }    BigInteger operator % (const BigInteger& b) const { //·½·¨Óë³ý·¨Ïàͬ        BigInteger c = *this;        BigInteger m;        for (int i = s.size()-1; i >= 0; i--) {            m = m*BASE + s[i];            c.s[i] = bsearch(b, m);            m -= b*c.s[i];        }        return m;    }    // ¶þ·Ö·¨ÕÒ³öÂú×ãbx<=mµÄ×î´óµÄx    int bsearch(const BigInteger& b, const BigInteger& m) const{        int L = 0, R = BASE-1, x;        while (1) {            x = (L+R)>>1;            if (b*x<=m) {if (b*(x+1)>m) return x; else L = x;}            else R = x;        }    }    BigInteger& operator += (const BigInteger& b) {*this = *this + b; return *this;}    BigInteger& operator -= (const BigInteger& b) {*this = *this - b; return *this;}    BigInteger& operator *= (const BigInteger& b) {*this = *this * b; return *this;}    BigInteger& operator /= (const BigInteger& b) {*this = *this / b; return *this;}    BigInteger& operator %= (const BigInteger& b) {*this = *this % b; return *this;}    bool operator < (const BigInteger& b) const {        if (s.size() != b.s.size()) return s.size() < b.s.size();        for (int i = s.size()-1; i >= 0; i--)            if (s[i] != b.s[i]) return s[i] < b.s[i];        return false;    }    bool operator >(const BigInteger& b) const{return b < *this;}    bool operator<=(const BigInteger& b) const{return !(b < *this);}    bool operator>=(const BigInteger& b) const{return !(*this < b);}    bool operator!=(const BigInteger& b) const{return b < *this || *this < b;}    bool operator==(const BigInteger& b) const{return !(b < *this) && !(b > *this);}};ostream& operator << (ostream& out, const BigInteger& x) {    out << x.s.back();    for (int i = x.s.size()-2; i >= 0; i--) {        char buf[20];        sprintf(buf, "%08d", x.s[i]);        for (int j = 0; j < strlen(buf); j++) out << buf[j];    }    return out;}istream& operator >> (istream& in, BigInteger& x) {    string s;    if (!(in >> s)) return in;    x = s;    return in;}BigInteger p2[410];#define MAXN (10000)int a[MAXN];void pre(int n){    Rep(i,n) a[i]=i;}bool vis[MAXN];BigInteger polya(int k,int *a,int n) { //Öû»²»¶¯µã¸öÊý     Rep(i,n) vis[i]=0;    int p=0;    Rep(i,n) if (!vis[i]) {        int j=i;        do {            vis[j]=1;            j=a[j];        }while(!vis[j]);        ++p;    }    return p2[p];}int a2[MAXN];int main(){    freopen("tickets.in","r",stdin);    freopen("tickets.out","w",stdout);    int n=read(),m=read();    pre(n*m);    p2[1]=2;    Fork(i,2,n*m) p2[i]=p2[i-1]*2;    BigInteger ans=0;    pre(n*m);    Rep(i2,n) {        Rep(j2,m) {            Rep(i,n) Rep(j,m)                a[i*m+j] = (i2+i)%n*m+(j+j2)%m;            ans+=polya(2,a,n*m);            if (n==m) {                Rep(i,n) Rep(j,m) {                    a2[i*m+j] = a[(n-j-1)*m+i];                }                ans+=polya(2,a2,n*m);            }            Rep(i,n) Rep(j,m) {                a[(n-i-1)*m+(m-j-1)] = (i2+i)%n*m+(j+j2)%m;            }            ans+=polya(2,a,n*m);            if (n==m) {                Rep(i,n) Rep(j,m) {                    a2[i*m+j] = a[(n-j-1)*m+i];                }                ans+=polya(2,a2,n*m);            }        }    }    ans/=(n*m*2);    if (n==m) ans/=2;    cout<<ans<<endl;    return 0;}
原创粉丝点击