zoukankan      html  css  js  c++  java
  • 调整法

    感觉就是一个类似爬山的东西
    调整很优的情形:
    调整严格不变劣
    要能尽量多调
    如果调不下去,可以找到两个颜色构成的连通块,把这个连通块颜色反转
    有一张无向图,她想对顶点3染色,满足相同颜色顶点之间没有连边。给出一个方案

    1. 给每个点随机赋三种颜⾊之⼀
    2. 将所有点扫⼀遍。扫到 号点时,考虑固定其他节点颜⾊调整 号点颜⾊,使得同⾊边数最少。如有
      多种选择,可随机⼀个。
    3. 重复步骤2,直到没有同⾊边。 容易发现,同⾊边数是不减的。⽽严格不变劣、可⼀直进⾏的调整
      对许多题⽬都很优秀。
    #include<bits/stdc++.h>
    using namespace std;
    #define fp(i,l,r) for(register int (i)=(l);i<=(r);++(i))
    #define fd(i,l,r) for(register int (i)=(l);i>=(r);--(i))
    #define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
    #define mem(a) memset((a),0,sizeof (a))
    #define O(x) cerr<<#x<<':'<<x<<endl
    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;
    }
    void wr(int x){
        if(x<0)putchar('-'),x=-x;
        if(x>=10)wr(x/10);
        putchar('0'+x%10);
    }
    const int MAXN=2e5+10;
    vector<int>E[MAXN];
    int col[MAXN],n,m,cnt[4],a[MAXN],b[MAXN];
    main(){
    	srand(time(0));
    	n=read();m=read();
    	fp(i,1,m){
    		a[i]=read();b[i]=read();
    		E[a[i]].push_back(b[i]);E[b[i]].push_back(a[i]);
    	}
    	fp(i,1,n)col[i]=rand()%3+1;
    	while(1){
    		fp(i,1,n){
    			mem(cnt);
    			for(int x:E[i])++cnt[col[x]];
    			int mn=1e9,p;
    			fp(j,1,3)if(cnt[j]<mn||(cnt[j]==mn&&(rand()&1)))p=j,mn=cnt[j];
    			col[i]=p;
    		}
    		fp(i,1,m)if(col[a[i]]==col[b[i]])goto ss;
    		fp(i,1,n)printf("%d ",col[i]);puts("");return 0;
    		ss:;
    	}
    }
    

    「JOISC 2020 Day4」传奇团子师傅
    别人说的最少60分的算法我就能实现成49分 弱到了极致 而且写了半天
    先随机一个加点的顺序
    如果有可以串但没串的 串上
    否则 有串了之后只和一个矛盾的 以一半概率串上并替代原来的

    #include<bits/stdc++.h>
    using namespace std;
    #define fp(i,l,r) for(register int (i)=(l);i<=(r);++(i))
    #define fd(i,l,r) for(register int (i)=(l);i>=(r);--(i))
    #define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next)
    #define mem(a) memset((a),0,sizeof (a))
    #define O(x) cerr<<#x<<':'<<x<<endl
    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;
    }
    void wr(int x){
        if(x<0)putchar('-'),x=-x;
        if(x>=10)wr(x/10);
        putchar('0'+x%10);
    }
    const int MAXN=2010;
    const int fx[]={-1,-1,0,1},fy[]={0,1,1,1};
    char mp[MAXN][MAXN];
    int id[MAXN][MAXN],n,m,cnt,book[MAXN][MAXN];
    pair<int,int>buc[MAXN*MAXN];
    inline void mark(int x,int y,int j){
    	int x1=x-fx[j],y1=y-fy[j],x2=x+fx[j],y2=y+fy[j];
    	book[x1][y1]=book[x2][y2]=id[x][y];book[x][y]=j;
    }
    inline void unmark(int p){
    	int x=buc[p].first,y=buc[p].second;int j=book[x][y];if(j==-1)return;
    	int x1=x-fx[j],y1=y-fy[j],x2=x+fx[j],y2=y+fy[j];
    	book[x1][y1]=book[x2][y2]=0;book[x][y]=-1;
    }
    inline bool check(int x,int y){return x>0&&y>0&&x<=n&&y<=m;}
    mt19937 gen(20020328);
    main(){
    	//freopen("input_05.txt","r",stdin);freopen("output_05.txt","w",stdout);
    	n=read();m=read();
    	fp(i,1,n){
    		scanf("%s",mp[i]+1);
    		fp(j,1,m)if(mp[i][j]=='W')id[i][j]=++cnt,book[i][j]=-1,buc[cnt]={i,j};
    	}
    	fp(tt,1,100){
    		fp(i,1,cnt){
    			int x=buc[i].first,y=buc[i].second;
    			fp(j,0,3){
    				int x1=x-fx[j],y1=y-fy[j],x2=x+fx[j],y2=y+fy[j];
    				if(!check(x1,y1)||!check(x2,y2))continue;
    				if(mp[x1][y1]=='W'||mp[x2][y2]=='W'||mp[x1][y1]==mp[x2][y2])continue;
    				if(!book[x1][y1]&&!book[x2][y2]){unmark(id[x][y]),mark(x,y,j);break;}//这里原先判了个如果已经匹配上了 以一半概率匹配新的 但加完了反而不优
    				else if(!book[x1][y1]&&book[x][y]==-1)if(gen()&1){unmark(book[x2][y2]);mark(x,y,j);}
    				else if(!book[x2][y2]&&book[x][y]==-1)if(gen()&1){unmark(book[x1][y1]);mark(x,y,j);}
    			}
    		}
    	}
    	fp(i,1,n){
    		fp(j,1,m){
    			if(mp[i][j]=='W'){
    				int t=book[i][j];
    				if(t==-1)putchar('W');
    				else if(t==0)putchar('|');
    				else if(t==1)putchar('/');
    				else if(t==2)putchar('-');
    				else putchar('\');
    			}
    			else putchar(mp[i][j]);
    		}
    		putchar('
    ');
    	}
    	return 0;
    }
    

    给出一张m个点n条边的简单图,要求构造一组用4种颜色给所有点染色的方案,使
    得每个点最多与一个与其同色的点相邻。
    保证每个点的度数不大于(7)
    首先让每个点随机染色
    考虑一个点(x),如果它相邻的点有至少两个和它颜色相同,则我们至少能找到一种颜
    (c),使得它相邻的点中颜色c出现不超过1次 ( ightarrow)(x)的颜色改成(c)
    代码不是我写的。。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    typedef vector<int> vi;
    typedef vector<vi> vvi;
    
    int main()
    {
    	int n, m;
    	
    	scanf("%d%d", &m, &n);
    	
    	vvi g(n + 1);
    	
    	for (int i = 1; i <= m; ++i)
    	{
    		int u, v;
    		scanf("%d%d", &u, &v);
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	
    	vi a(n + 1);
    	
    	vector<bool> inq(n + 1);
    	queue<int> q;
    	
    	for (int i = 1; i <= n; ++i)
    	{
    		inq[i] = true;
    		q.push(i);
    	}
    
    	while (!q.empty())
    	{
    		int u = q.front();
    		inq[u] = false;
    		q.pop();
    		
    		vi cnt(4);
    		
    		for (auto v : g[u]) ++cnt[a[v]];
    		
    		if (cnt[a[u]] >= 2)
    		{
    			for (int i = 0; i < 4; ++i)
    			{
    				if (cnt[i] <= 1)
    				{
    					a[u] = i;
    					break;
    				}
    			}
    			for (auto v : g[u])
    			{
    				if (!inq[v])
    				{
    					inq[v] = true;
    					q.push(v);
    				}
    			}
    		}
    	}
    	
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 1; j <= 4; ++j)
    		{
    			if (j != a[i] + 1)
    			{
    				printf("%d ", j);
    			}
    		}
    		puts("");
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    dedecms likearticle 调用附加表的字段调用方式
    织梦dedecms自定义字段在首页列表页文章页的调用
    织梦系统站点首页、列表、文章页等页面点击数调用方法
    dedecms友情链接flink的调用方法
    织梦dedecms5.7后台进去就卡死解决方法
    Dede修改文章默认标题长度,让标题全显示
    dede调用时间大全标签,不同格式!
    dede调用指定栏目的标签
    python time模块的使用
    phpstudy 环境使用Composer安装thinkphp并指定版本
  • 原文地址:https://www.cnblogs.com/WinterSpell/p/13473087.html
Copyright © 2011-2022 走看看