#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof x)
#define For(i,a,b) for (int i=(a);i<=(b);i++)
#define Fod(i,b,a) for (int i=(b);i>=(a);i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define outval(x) cerr<<#x" = "<<x<<endl
#define outtag(x) cerr<<"-----------------"#x"-----------------\n"
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
                    For(_x,L,R) cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> pii;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return f?-x:x;
}
const int N=100005,mod=1e9+7;
int Pow(int x,int y){
	int ans=1;
	for (;y;y>>=1,x=(LL)x*x%mod)
		if (y&1)
			ans=(LL)ans*x%mod;
	return ans;
}
void Add(int &x,int y){
	if ((x+=y)>=mod)
		x-=mod;
}
void Del(int &x,int y){
	if ((x-=y)<0)
		x+=mod;
}
int Add(int x){
	return x>=mod?x-mod:x;
}
int Del(int x){
	return x<0?x+mod:x;
}
int n,m;
int v[N][2];
struct Edge{
	int fx,x,fy,y;
	Edge(){}
	Edge(int _fx,int _x,int _fy,int _y){
		fx=_fx,x=_x,fy=_fy,y=_y;
	}
};
vector <Edge> e[N];
int vis[N];
int ans0=1,ans1=0;
void Ins(int v0,int v1){
	int tmp0=((LL)ans0*v0+(LL)ans1*v1)%mod;
	int tmp1=((LL)ans0*v1+(LL)ans1*v0)%mod;
	ans0=tmp0,ans1=tmp1;
}
void Solve1(int s){
	vector <int> id;
	vector <Edge> ed;
	int t=s,flag=1;
	while (flag){
		vis[t]=1,id.pb(t),flag=0;
		for (auto i : e[t])
			if (!vis[i.y]){
				ed.pb(i),flag=1,t=i.y;
				break;
			}
	}
	vector <int> dp[2][2];
	For(i,0,1)
		For(j,0,1)
			dp[i][j].resize(id.size(),0);
	dp[v[id[0]][0]][0][0]++;
	dp[v[id[0]][1]][1][0]++;
	int sz=(int)id.size()-1;
	For(i,0,sz-1){
		int fx=ed[i].fx,fy=ed[i].fy;
		For(a,0,1) For(b,0,1) For(c,0,1)
			Add(dp[c^((a^fx)|(b^fy))^v[id[i+1]][b]][b][i+1],dp[c][a][i]);
	}
	int v0=Add(dp[0][0][sz]+dp[0][1][sz]);
	int v1=Add(dp[1][0][sz]+dp[1][1][sz]);
	Ins(v0,v1);
}
void Solve2(int s){
	vector <int> id;
	vector <Edge> ed;
	int t=s,flag=1;
	while (flag){
		vis[t]=1,id.pb(t),flag=0;
		for (auto i : e[t])
			if (!vis[i.y]){
				ed.pb(i),flag=1,t=i.y;
				break;
			}
	}
	Edge Et=e[s][1];
	int tfx=Et.fx,tfy=Et.fy;
	vector <int> dp[2][2];
	int v0=0,v1=0;
	For(i,0,1)
		For(j,0,1)
			dp[i][j].resize(id.size(),0);
	int sz=(int)id.size()-1;
	dp[v[id[0]][0]][0][0]++;
	For(i,0,sz-1){
		int fx=ed[i].fx,fy=ed[i].fy;
		For(a,0,1) For(b,0,1) For(c,0,1)
			Add(dp[c^((a^fx)|(b^fy))^v[id[i+1]][b]][b][i+1],dp[c][a][i]);
	}
	For(a,0,0) For(b,0,1) For(c,0,1){
		Add(c^((a^tfx)|(b^tfy))?v1:v0,dp[c][b][sz]);
		for (auto &i : dp[c][b])
			i=0;
	}
	dp[v[id[0]][1]][1][0]++;
	For(i,0,sz-1){
		int fx=ed[i].fx,fy=ed[i].fy;
		For(a,0,1) For(b,0,1) For(c,0,1)
			Add(dp[c^((a^fx)|(b^fy))^v[id[i+1]][b]][b][i+1],dp[c][a][i]);
	}
	For(a,1,1) For(b,0,1) For(c,0,1)
		Add(c^((a^tfx)|(b^tfy))?v1:v0,dp[c][b][sz]);
	Ins(v0,v1);
}
int main(){
	n=read(),m=read();
	For(i,1,n){
		int k=read();
		if (k==1){
			int x=read();
			v[abs(x)][x>0]^=1;
		}
		else {
			int x=read(),y=read(),fx=x<0,fy=y<0;
			x=abs(x),y=abs(y);
			if (x==y){
				if (fx!=fy)
					Ins(0,2);
				else
					Ins(1,1);
				vis[x]=1;
				continue;
			}
			e[x].pb(Edge(fx,x,fy,y));
			e[y].pb(Edge(fy,y,fx,x));
		}
	}
	For(i,1,m)
		if (!vis[i]&&e[i].size()==0){
			vis[i]=1;
			int val=v[i][0]+v[i][1];
			Ins(2-val,val);
		}
	For(i,1,m)
		if (!vis[i]&&e[i].size()==1)
			Solve1(i);
	For(i,1,m)
		if (!vis[i])
			Solve2(i);
	cout<<ans1<<endl;
	return 0;
}


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool mfc[101000];
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
			vis[abs(id[j])]=0;
			if(id[j]<0)
			   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
				{
					swap(ans[0],ans[1]);
					ans[0]=(ans[0]<<1)%mod;
					ans[1]=(ans[1]<<1)%mod;
				}
				mfc[abs(id[0])]=true;
				continue;
			}
		}
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
        if(mfc[i])
        {
        	vs[i]=true;
        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     //printf("j=%d\n",j);
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
					   {
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				  	  	 // printf("dp[%d][0][%d]=%d,dp[%d][1][%d]=%d\n",ip,j,dp[ip][0][0][j],ip,j,dp[ip][0][1][j]);
					   }
				 }
 			 	 else
				 {
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	//printf("ans[0]=%d,ans[1]=%d\n",ans[0],ans[1]);
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
	            //printf("ip=%d,j=%d,pre=%d,ipen=%d\n",ip,j,pre,adj[ip][j].ip);
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        //printf("dp[%d][%d][%d][%d]=%d\n",ip,s,p,k,dp[ip][s][p][k]);
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                //puts("orz");
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
            //for(j=0;j<2;j++)
 		  // int vl[2];
	       //vl[0]=vl[1]=0;
	       for(j=0;j<2;j++)
	       {
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		     //  printf("dp[%d]=%d,dp[%d]=%d\n",j,dp[i][0][0][j],j,dp[i][1][1][j]);
		       //printf("vl[%d]=%d\n",j,vl[j]);
	       }
	       /*
		   int mvp[2];
	       mvp[0]=mvp[1]=0;
		   for(j=0;j<2;j++)
		   {
		   	   if(ans[j]==0)
		   	      continue;
         	   for(s=0;s<2;s++)
		       {
       			   if(vl[s]==0)
       			      continue;
   			       mvp[j^s]+=(int)((long long)ans[j]*(long long)vl[s]%mod);
   			       mvp[j^s]%=mod;
       		   }
       	   }
       	   ans[0]=mvp[0];
       	   ans[1]=mvp[1];
       	   */
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}
/*
dp[4][0][0]=3,dp[4][1][0]=3
dp[4][0][1]=1,dp[4][1][1]=1
dp[10][0][0]=20,dp[10][1][0]=20
dp[10][0][1]=12,dp[10][1][1]=12
dp[7][0][0]=224,dp[7][1][0]=256
dp[7][0][1]=288,dp[7][1][1]=256
ans[0]=480,ans[1]=544
544

*/


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
			vis[abs(id[j])]=0;
			if(id[j]<0)
			   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
					swap(ans[0],ans[1]);
				continue;
			}
		}
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				 }
 			 	 else
				 {
				 	vs[i]=true;
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
	       for(j=0;j<2;j++)
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
		//	vis[abs(id[j])]=0;
		//	if(id[j]<0)
		//	   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
					swap(ans[0],ans[1]);
				continue;
			}
		}
		for(j=0;j<num;j++)
		{
			vis[abs(id[j])]=0;
			if(id[j]<0)
			  vis[abs(id[j])]=1;
		}
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				 }
 			 	 else
				 {
				 	vs[i]=true;
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
	       for(j=0;j<2;j++)
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
		//	vis[abs(id[j])]=0;
		//	if(id[j]<0)
		//	   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
				{
					swap(ans[0],ans[1]);
			    	continue;
				}
			}
		}
		for(j=0;j<num;j++)
		{
			vis[abs(id[j])]=0;
			if(id[j]<0)
			  vis[abs(id[j])]=1;
		}
		if(id[0]==id[1])
		   continue;
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				 }
 			 	 else
				 {
				    	vs[i]=true;
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
	       for(j=0;j<2;j++)
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool mfc[101000];
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
			vis[abs(id[j])]=0;
			if(id[j]<0)
			   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
				{
					swap(ans[0],ans[1]);
					ans[0]=(ans[0]<<1)%mod;
					ans[1]=(ans[1]<<1)%mod;
                    mfc[abs(id[0])]=true;
				}
				continue;
			}
		}
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
        if(mfc[i])
        {
        	vs[i]=true;

        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     //printf("j=%d\n",j);
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
					   {
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				  	  	 // printf("dp[%d][0][%d]=%d,dp[%d][1][%d]=%d\n",ip,j,dp[ip][0][0][j],ip,j,dp[ip][0][1][j]);
					   }
				 }
 			 	 else
				 {
				 	vs[i]=true;
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	//printf("ans[0]=%d,ans[1]=%d\n",ans[0],ans[1]);
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
	            //printf("ip=%d,j=%d,pre=%d,ipen=%d\n",ip,j,pre,adj[ip][j].ip);
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        //printf("dp[%d][%d][%d][%d]=%d\n",ip,s,p,k,dp[ip][s][p][k]);
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                //puts("orz");
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
            //for(j=0;j<2;j++)
 		  // int vl[2];
	       //vl[0]=vl[1]=0;
	       for(j=0;j<2;j++)
	       {
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		     //  printf("dp[%d]=%d,dp[%d]=%d\n",j,dp[i][0][0][j],j,dp[i][1][1][j]);
		       //printf("vl[%d]=%d\n",j,vl[j]);
	       }
	       /*
		   int mvp[2];
	       mvp[0]=mvp[1]=0;
		   for(j=0;j<2;j++)
		   {
		   	   if(ans[j]==0)
		   	      continue;
         	   for(s=0;s<2;s++)
		       {
       			   if(vl[s]==0)
       			      continue;
   			       mvp[j^s]+=(int)((long long)ans[j]*(long long)vl[s]%mod);
   			       mvp[j^s]%=mod;
       		   }
       	   }
       	   ans[0]=mvp[0];
       	   ans[1]=mvp[1];
       	   */
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}
/*
dp[4][0][0]=3,dp[4][1][0]=3
dp[4][0][1]=1,dp[4][1][1]=1
dp[10][0][0]=20,dp[10][1][0]=20
dp[10][0][1]=12,dp[10][1][1]=12
dp[7][0][0]=224,dp[7][1][0]=256
dp[7][0][1]=288,dp[7][1][1]=256
ans[0]=480,ans[1]=544
544

*/


#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<vector>
using namespace std;
const int mod=1e9+7;
int n,m;
struct pp
{
	int id,flag,ip;
};
vector<pp>adj[101000];
int vis[101000],list[101000],dp[101000][2][2][2],ans[2],cnt;
bool vs[101000];
int main()
{
	scanf("%d%d",&m,&n);
	int i,j,s,p,q,k,t,num,id[2],ip,pre;
	memset(vis,-1,sizeof(vis));
	cnt=0;
	ans[0]=1;
	ans[1]=0;
	for(i=0;i<m;i++)
	{
		scanf("%d",&num);
		for(j=0;j<num;j++)
		{
			scanf("%d",&id[j]);
			vis[abs(id[j])]=0;
			if(id[j]<0)
			   vis[id[j]]=1;
		}
		pp now;
		if(num==2)
		{
			if(abs(id[0])==abs(id[1]))
			{
				if(id[0]+id[1]==0)
					swap(ans[0],ans[1]);
				continue;
			}
		}
		if(num==2)
		{
			now.id=abs(id[1]);
			now.flag=0;
			if(id[0]<0)
			   now.flag|=1;
            if(id[1]<0)
               now.flag|=2;
            now.ip=cnt++;
            adj[abs(id[0])].push_back(now);
            now.id=abs(id[0]);
            now.flag=0;
            if(id[1]<0)
               now.flag|=1;
            if(id[0]<0)
               now.flag|=2;
            adj[abs(id[1])].push_back(now);
		}
	}
	for(i=1;i<=n;i++)
	{
		if(vs[i])
		   continue;
		if(vis[i]<0)
        {
        	vs[i]=true;
        	ans[0]=(ans[0]<<1)%mod;
        	ans[1]=(ans[1]<<1)%mod;
        	continue;
        }
		if(adj[i].size()<=1)
		{
				 pre=-1;
				 ip=i;
				 if(adj[i].size()==1)
				 {
			 	    for(j=0;j<2;j++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ip][j][s][p]=0;
    				 dp[ip][0][0][0]=ans[0];
	    			 dp[ip][0][0][1]=ans[1];
		    		 dp[ip][0][1][0]=ans[0];
			    	 dp[ip][0][1][1]=ans[1];
			    	 while(true)
			    	 {
 			    		 int ch=-1;
 			    		 vs[ip]=true;
 			  		     for(j=0;j<adj[ip].size();j++)
 			  		     {
     		  			 	  if(adj[ip][j].id!=pre)
     		  			 	     break;
     		  			 }
     		  			 if(j>=adj[ip].size())
     		  			     break;
 		  			     ch=adj[ip][j].id;

	  			      	 for(int jj=0;jj<2;jj++)
                	        for(s=0;s<2;s++)
                	           for(p=0;p<2;p++)
                	              dp[ch][jj][s][p]=0;
 		  			     for(s=0;s<2;s++)
     			  		 	 for(p=0;p<2;p++)
     			  		 	 {
 	 		  			         if(dp[ip][0][s][p]==0)
									continue;
								 for(q=0;q<2;q++)
								 {
								     int mv,ns=s^(adj[ip][j].flag&1);
							 	     if(adj[ip][j].flag&2)
								         mv=ns|(q^1);
					                 else
					                     mv=ns|q;
	                                 dp[ch][0][q][p^mv]=(dp[ch][0][q][p^mv]+dp[ip][0][s][p])%mod;
								 }
 	 		  			     }
	                     pre=ip;
 			             ip=ch;
 			    	 }
					   for(j=0;j<2;j++)
				  	  	  ans[j]=(dp[ip][0][0][j]+dp[ip][0][1][j])%mod;
				 }
 			 	 else
				 {
				 	vs[i]=true;
				 	   int ts=(ans[0]+ans[1])%mod;
				 	   ans[0]=ans[1]=ts;
 				 }
		}
	}
	for(i=1;i<=n;i++)
	{
		if(!vs[i])
		{
			pre=-1;
			ip=i;
		    for(j=0;j<2;j++)
               for(s=0;s<2;s++)
       	           for(p=0;p<2;p++)
       	              dp[ip][j][s][p]=0;
			for(j=0;j<2;j++)
               for(s=0;s<2;s++)
               	   dp[ip][j][j][s]=ans[s];
            while(true)
            {
            	int ch;
            	vs[ip]=true;
            	for(j=0;j<adj[ip].size();j++)
            	{
	            	if(adj[ip][j].ip!=pre)
	            		break;
	            }
                ch=adj[ip][j].id;
               	for(int jj=0;jj<2;jj++)
               	  for(s=0;s<2;s++)
                     for(p=0;p<2;p++)
                       dp[ch][jj][s][p]=0;
                for(s=0;s<2;s++)
                {
                	for(p=0;p<2;p++)
                	{
	                	for(k=0;k<2;k++)
	                	{
	                		if(dp[ip][s][p][k]==0)
	                		    continue;
             		        for(q=0;q<2;q++)
             		        {
        		             	if(ch==i&&q!=s)
        		             	   continue;
     		             	    int mv,np=p^(adj[ip][j].flag&1);
     		             	    if(adj[ip][j].flag&2)
     		             	       mv=np|(q^1);
  		             	        else
  		             	           mv=np|q;
	             	            dp[ch][s][q][k^mv]=(dp[ch][s][q][k^mv]+dp[ip][s][p][k])%mod;
        		            }
	                	}
	                }
                }
                if(ch==i)
                   break;
                pre=adj[ip][j].ip;
                ip=ch;
            }
	       for(j=0;j<2;j++)
		       ans[j]=(dp[i][0][0][j]+dp[i][1][1][j])%mod;
		}
	}
	printf("%d\n",ans[1]);
	return 0;
}//


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-6;
int N, M, X;
vector<tuple<int,int,double>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(double w) {
  Dinics<long long> d(N);
  for (auto e : edges) {
    int a,b; double c;
    a = get<0>(e); b = get<1>(e); c = get<2>(e);
    d.add_edge(a,b,min((double)X, c/w));
  }

  return d.max_flow(0,N-1) >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi; double ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  double lo,hi;
  lo = 0; hi = 1e6 + EPS;
  while (X*hi - X*lo > EPS) {
    double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  cout << fixed << setprecision(10) << lo * X << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-10;
int N, M, X;
vector<tuple<int,int,int>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(double w) {
  Dinics<int> d(N);
  for (auto e : edges) {
    int a,b; double c;
    a = get<0>(e); b = get<1>(e); c = (double)get<2>(e);
    d.add_edge(a,b,c/w);
  }

  int flow = d.max_flow(0,N-1);
  // cerr << "w :" << w << " flow: " << flow << endl;

  return flow >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi,ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  double lo,hi;
  lo = 0; hi = 1e6+EPS;
  while (hi - lo > EPS) {
    double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  printf("%.10lf\n", lo*X);
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-6;
int N, M, X;
vector<tuple<int,int,int>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(double w) {
  Dinics<int> d(N);
  for (auto e : edges) {
    int a,b,c;
    a = get<0>(e); b = get<1>(e); c = get<2>(e);
    d.add_edge(a,b,(c*1.0)/w);
  }

  int flow = d.max_flow(0,N-1);

  return flow >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi,ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  double lo,hi;
  lo = 0; hi = 1e6 + EPS;
  while (X*hi - X*lo > EPS) {
    double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  cout << fixed << setprecision(10) << lo * X << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-6;
int N, M, X;
vector<tuple<int,int,double>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(long double w) {
  Dinics<long long> d(N);
  for (auto e : edges) {
    int a,b; long double c;
    a = get<0>(e); b = get<1>(e); c = get<2>(e);
    d.add_edge(a,b,min<long double>(X, c/w));
  }

  return d.max_flow(0,N-1) >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi; double ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  long double lo,hi;
  lo = 0; hi = 1e6 + EPS;
  while (X*hi - X*lo > EPS) {
    long double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  cout << fixed << setprecision(10) << lo * X << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-10;
int N, M, X;
vector<tuple<int,int,int>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(double w) {
  Dinics<int> d(N);
  for (auto e : edges) {
    int a,b,c;
    a = get<0>(e); b = get<1>(e); c = get<2>(e);
    d.add_edge(a,b,(c*1.0)/w);
  }

  int flow = d.max_flow(0,N-1);

  return flow >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi,ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  double lo,hi;
  lo = 0; hi = 1e6 + EPS;
  while (X*hi - X*lo > EPS) {
    double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  cout << fixed << setprecision(10) << lo * X << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;

double EPS = 1e-10;
int N, M, X;
vector<tuple<int,int,int>> edges;

template < typename T> struct Dinics {
struct edge { int to; T flow , cap ; }; T INF = numeric_limits <T >:: max ();
int n, m; vi dist , work ; queue <int > q; vector <edge > edges ; vvi adj ;
bool bfs ( int s, int t) {
dist . assign (n, -1); dist [s] = 0; q. push (s);
while (!q. empty ()) {
int u = q. front (); q. pop ();
for ( auto & i : adj[u]) {
edge & e = edges [i]; int v = e.to;
if ( dist [v] < 0 && e. flow < e. cap) dist [v] = dist [u] + 1, q. push (v);
}
}
return dist [t] >= 0;
}T
dfs( int u, int t, T f) {
if (u == t) return f;
for (int& i = work [u]; i < ( int ) adj [u]. size (); i ++) {
auto & e = edges [ adj [u][i]], & rev = edges [ adj [u][i ]^1];
if (e. flow < e. cap && dist [e.to] == dist [u] + 1) {
T df = dfs (e.to , t, min(f, e.cap - e. flow ));
if (df > 0) { e. flow += df; rev . flow -= df; return df; }
}
}
return 0;
}
// Create a flow network with n nodes -- add edges with add_edge (u,v, cap )
Dinics ( int n) : n(n), m (0) , adj (n) { }
int add_edge ( int from , int to , T cap ) { // add an edge ( from -> to) with
adj [ from ]. push_back (m++) , adj [to ]. push_back (m ++) ; // capacity of cap units .
edges . push_back ({to , 0, cap }) , edges . push_back ({ from , 0, 0}) ;
return m - 2; // Change {from ,0 ,0} to {from ,0, cap } for bidirectional edges
}
edge & get_edge ( int i) { return edges [i]; } // get a reference to the i’th edge
T max_flow ( int s, int t) { // find the maximum flow from s to t
T res = 0; for ( auto & e : edges ) e. flow = 0;
while ( work . assign (n, 0) , bfs (s, t))
while (T delta = dfs (s, t, INF )) res += delta ;
return res;
}
};

bool f(double w) {
  Dinics<int> d(N);
  for (auto e : edges) {
    int a,b; double c;
    a = get<0>(e); b = get<1>(e); c = (double)get<2>(e);
    d.add_edge(a,b,c/w);
  }

  int flow = d.max_flow(0,N-1);
  // cerr << "w :" << w << " flow: " << flow << endl;

  return flow >= X;
}

int main() {
  cin >> N >> M >> X;

  edges.resize(M);
  for (int i=0;i<M;i++) {
    int ai,bi,ci; cin >> ai >> bi >> ci;
    ai--;bi--;
    edges[i] = make_tuple(ai,bi,ci);
  }

  double lo,hi;
  lo = 0; hi = 2e6;
  while (hi - lo > EPS) {
    double mid = (lo+hi)/2;
    if (f(mid)) {
      lo = mid;
    }
    else hi = mid;
  }

  printf("%.10lf\n", lo*X);
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int seen[V];

int inv(int e) { return e ^ 1; }

bool augment(int u, int t, double f) {
  if (u == t) return true;                     // the path is empty!
  if (seen[u]) return false;
  seen[u] = true;
  for (int e = start[u]; ~e; e = succ[e])
    if (cap[e] >= f && augment(to[e], t, f)) { // if we can reach the end,
      cap[e] -= f;                             // use this edge
      cap[inv(e)] += f;                        // allow "cancelling out"
      return true;
    }
  return false;
}

double max_flow(int s, int t) {
  double res = 0;
  fill(seen, seen + V, 0);
  while (augment(s, t, 1)) {
    fill(seen, seen + V, 0);
    res += 1;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }
  cout.precision(10);
  cout << x * low << '\n';
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }
  cout.precision(10);
  cout << x * low << '\n';
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
      high += 0.001;
    }
    else {
      high = val;
    }
    //if (n == 50 && high < 100) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';
/*
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
*/
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
    if (n == 50 && high < 10) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 1000; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }
  cout.precision(10);
  cout << x * low << '\n';
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
    if (n == 50) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
      high += 0.001;
    }
    else {
      high = val;
    }
    if (n == 50 && count > 90) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';

  if (n == 50) {
    double val = 41.6;
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);

    cout << maxflow << '\n';
  }

}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
      high += 0.001;
    }
    else {
      high = val;
    }
    if (n == 50 && count > 90) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';
/*
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
*/
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
      high += 0.001;
    }
    else {
      high = val;
    }
    if (n == 50 && count > 90) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';

  if (n == 50) {
    double val = 41.600845;
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);

    cout << maxflow << '\n';
  }

}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
    if (n == 50 && high < 100) cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
  cout.precision(10);
  cout << x * low << '\n';
  if (n == 50) {
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/((low + high)/2);
    }
    int maxflow = max_flow(1, n);

    cout << low << ' ' << high << ' ' << maxflow << '\n';
  }
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int seen[V];

int inv(int e) { return e ^ 1; }

bool augment(int u, int t, double f) {
  if (u == t) return true;                     // the path is empty!
  if (seen[u]) return false;
  seen[u] = true;
  for (int e = start[u]; ~e; e = succ[e])
    if (cap[e] >= f && augment(to[e], t, f)) { // if we can reach the end,
      cap[e] -= f;                             // use this edge
      cap[inv(e)] += f;                        // allow "cancelling out"
      return true;
    }
  return false;
}

double max_flow(int s, int t) {
  double res = 0;
  fill(seen, seen + V, 0);
  while (augment(s, t, 1)) {
    fill(seen, seen + V, 0);
    res += 1;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }

  cout << x * low << '\n';
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

double augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 100; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = floor(oldcap[i]/val);
    }
    double maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }
  cout.precision(10);
  cout << x * low << '\n';
/*
    double val = 0.5;
    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    double maxflow = max_flow(1, n);

    cout << maxflow << '\n';
*/
}


#include <bits/stdc++.h>
using namespace std;

const int E = 500 * 5;
const int V = 50 * 5;
// the index of the first outgoing edge for each vertex, initialised to -1
int start[V];
// if e is an outgoing edge from u, succ[e] is another one, or -1
// cap[e] is the capacity/weight of the e
// to[e] is the destination vertex of e
int succ[E], to[E];
double cap[E], oldcap[E];

int edge_counter = 0;
void add_edge(int u, int v, double c) {
  // set the properties of the new edge
  cap[edge_counter] = c, to[edge_counter] = v;
  oldcap[edge_counter] = c;
  // insert this edge at the start of u's linked list of edges
  succ[edge_counter] = start[u];
  start[u] = edge_counter;
  ++edge_counter;
}
int path[V];

int inv(int e) { return e ^ 1; }

int augment(int s, int t) {
  // This is a BFS, shortest path means by edge count not capacity
  queue<int> q;
  // path[v] = which edge we used from to reach v
  fill(path, path + V, -1);
  for (q.push(s), path[s] = -2; !q.empty(); q.pop()) {
    int u = q.front();
    for (int e = start[u]; ~e; e = succ[e]) {
      // if we can use e and we haven't already visited v, do it
      if (cap[e] <= 0) continue;
      int v = to[e];
      if (path[v] == -1) {
        path[v] = e;
        q.push(v);
      }
    }
  }
  if (path[t] == -1) return 0; // can't reach the sink
  double res = 1e9;
  // walk over the path backwards to find the minimum edge
  for (int e = path[t]; e != -2; e = path[to[inv(e)]])
    res = min(res, cap[e]);
  // do it again to subtract that from the capacities
  for (int e = path[t]; e != -2; e = path[to[inv(e)]]) {
    cap[e] -= res;
    cap[inv(e)] += res;
  }
  return res;
}

double max_flow(int s, int t) {
  double res = 0;
  double difference;
  while (difference = augment(s, t)) {
    res += difference;
  }
  return res;
}

int main() {
  for (int i = 0; i < V; i++) start[i] = -1;
  for (int i = 0; i < E; i++) succ[i] = -1;

  int n, m, x;
  cin >> n >> m >> x;
  for (int i = 0; i < m; i++) {
    int a, b, c;
    cin >> a >> b >> c;
    add_edge(a, b, c);
    add_edge(b, a, 0);
  }

  double low = 0, high = 1e12;
  for (int count = 0; count < 1000; count++)  {
    double val = (low + high) / 2;

    for (int i = 0; i < edge_counter; i++) {
      cap[i] = oldcap[i]/val;
    }
    int maxflow = max_flow(1, n);
    if (maxflow >= x) {
      low = val;
    }
    else {
      high = val;
    }
  }
  cout.precision(10);
  cout << x * low << '\n';
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, c[N][N], f[N][N], d[N], ptr[N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

int dfs(int u, int flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			int kk = (int) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, d[N], ptr[N];
long long c[N][N], f[N][N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

long long dfs(int u, long long flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
	return 0;
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(long double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			long long kk = (long long) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	for(int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
		graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, c[N][N], f[N][N], d[N], ptr[N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

int dfs(int u, int flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
	return 0;
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			int kk = (int) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	for(int i = 1; i <= n; i++) {
		sort(graph[u].begin(), graph[u].end());
		graph[u].erase(unique(graph[u].begin(), graph[u].end()), graph[u].end());
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, c[N][N], f[N][N], d[N], ptr[N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

int dfs(int u, int flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
	return 0;
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			int kk = (int) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, c[N][N], f[N][N], d[N], ptr[N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

int dfs(int u, int flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
	return 0;
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			int kk = (int) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	for(int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
		graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>
using namespace std;

const long double eps = 1e-11;
const int N = 1010, INF = 1e9 + 7;

int n, m, x, d[N], ptr[N];
long long c[N][N], f[N][N], C[N][N];
vector<int> graph[N];

bool bfs() {
	for(int i = 1; i <= n; i++) d[i] = INF, ptr[i] = 0;
	d[1] = 0;
	queue<int> wl; wl.push(1);
	while(not wl.empty()) {
		int u = wl.front(); wl.pop();
		for(int v : graph[u]) {
			if(d[v] == INF && f[u][v] < c[u][v]) {
				d[v] = d[u] + 1;
				wl.push(v);
			}
		}
	}
	return (d[n] != INF);
}

int dfs(int u, int flow) {
	if(u == n || not flow) return flow;
	for(int &i = ptr[u]; i < graph[u].size(); i++) {
		int v = graph[u][i];
		if(f[u][v] >= c[u][v] || d[v] != d[u] + 1) continue;
		int delta = dfs(v, min(flow, c[u][v] - f[u][v]));
		if(delta) {
			f[u][v] += delta, f[v][u] -= delta;
			return delta;
		}
	}
	return 0;
}

long long maxflow() {
	long long ans = 0;
	while(bfs()) {
		while(dfs(1, INF));
	}
	for(int u : graph[1]) ans += f[1][u];
	return ans;
}

bool check(long double val) {
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			long double k = (long double) C[i][j] / val;
			long long kk = (long long) k;
			if((long double) kk + 1 - k <= eps) kk++;
			c[i][j] = kk, f[i][j] = 0;
		}
	}
	return (maxflow() < x);
}

int main() {
	scanf("%d%d%d", &n, &m, &x);
	for(int i = 0; i < m; i++) {
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		C[u][v] = w;
		graph[u].push_back(v);
		graph[v].push_back(u);
	}
	for(int i = 1; i <= n; i++) {
		sort(graph[i].begin(), graph[i].end());
		graph[i].erase(unique(graph[i].begin(), graph[i].end()), graph[i].end());
	}
	long double len = 0, rin = 1e6;
	while(len + eps < rin) {
		long double miku = (len + rin)/2.0;
		if(check(miku)) rin = miku;
		else len = miku;
	}
	printf("%.11Lf", len * (long double) x);
}


#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define ll long long

using namespace std;

const ll inf = 1e18;
const int mod = 1e9 + 7;

long double a[505], b[505], c[505];
vector <int> used(51);
vector <vector <int> > g;
int n,m,x;

int dfs(int v, int pushed){
  if (v == n) return pushed;
  int flow = 0;
  used[v] = 1;
  for (int i=1;i<=n;i++){
    if (!used[i]  && g[v][i]){
      int cur = dfs(i, min(pushed,g[v][i]));
      flow += cur;
      pushed -= cur;
      g[v][i] -= cur;
      g[i][v] += cur;
    }
  }
  return flow;
}

int maxflow(){
  int flow = 0;
  //used.resize(n);
  used.assign(n+1,0);
  int add = dfs(1,1e9);
  while (add){
    flow += add;
    used.assign(n+1,0);
    add = dfs(1,1e9);
  }
  return flow;
}

bool check(long double k){
  for (int i=0;i<m;i++){
    g[a[i]][b[i]] = floor(c[i] / k);
  }
  if (maxflow() >= x)  return true;
  return false;
}

int main(){
  ios_base::sync_with_stdio(0);
  //freopen("input.txt", r, stdin);
  //freopen("output.txt", w, stdout);
  cin >> n >> m >> x;
  g.resize(n+1);
  for (int i=0;i<=n;i++){
    g[i].resize(n+1);
  }
  for (int i=0;i<m;i++){
    cin >> a[i] >> b[i] >> c[i];
  }
  long double l = 0.0, r = 1000001.0;
  for (int i=0;i<1337;i++){
    long double mid = (l + r) * 0.5;
    if (check(mid)) l = mid;
    else r = mid;
  }
  cout << fixed << setprecision(10) << l * x << endl;
}


#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define ll long long

using namespace std;

const ll inf = 1e18;
const int mod = 1e9 + 7;

long double a[505], b[505], c[505];
vector <int> used(51);
vector <vector <ll> > g;
int n,m,x;

ll dfs(int v, ll pushed){
  if (v == n) return pushed;
  ll flow = 0;
  used[v] = 1;
  for (int i=1;i<=n;i++){
    if (!used[i]  && g[v][i]){
      ll cur = dfs(i, min(pushed,g[v][i]));
      flow += cur;
      pushed -= cur;
      g[v][i] -= cur;
      g[i][v] += cur;
    }
  }
  return flow;
}

ll maxflow(){
  ll flow = 0;
  //used.resize(n);
  used.assign(n,0);
  ll add = dfs(1,1e9);
  while (add){
    flow += add;
    used.assign(n,0);
    add = dfs(1,1e9);
  }
  return flow;
}

bool check(long double k){
  for (int i=0;i<m;i++){
    g[a[i]][b[i]] = floor(c[i] / k);
  }
  if (maxflow() >= x)  return true;
  return false;
}

int main(){
  ios_base::sync_with_stdio(0);
  //freopen("input.txt", r, stdin);
  //freopen("output.txt", w, stdout);
  cin >> n >> m >> x;
  g.resize(n+1);
  for (int i=0;i<=n;i++){
    g[i].resize(n+1);
  }
  for (int i=0;i<m;i++){
    cin >> a[i] >> b[i] >> c[i];
  }
  long double l = 0.0, r = 10000001.0;
  for (int i=0;i<228;i++){
    long double mid = (l + r) * 0.5;
    if (check(mid)) l = mid;
    else r = mid;
  }
  cout << fixed << setprecision(10) << l * x << endl;
}


#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define ll long long

using namespace std;

const ll inf = 1e18;
const int mod = 1e9 + 7;

long double a[505], b[505], c[505];
vector <int> used(51);
vector <vector <int> > g;
int n,m,x;

int dfs(int v, int pushed){
  if (v == n) return pushed;
  int flow = 0;
  used[v] = 1;
  for (int i=1;i<=n;i++){
    if (!used[i]  && g[v][i]){
      int cur = dfs(i, min(pushed,g[v][i]));
      flow += cur;
      pushed -= cur;
      g[v][i] -= cur;
      g[i][v] += cur;
    }
  }
  return flow;
}

int maxflow(){
  int flow = 0;
  //used.resize(n);
  used.assign(n+1,0);
  int add = dfs(1,1e9);
  while (add){
    flow += add;
    used.assign(n+1,0);
    add = dfs(1,1e9);
  }
  return flow;
}

bool check(long double k){
  for (int i=0;i<m;i++){
    g[a[i]][b[i]] = floor(c[i] / k);
  }
  if (maxflow() >= x)  return true;
  return false;
}

int main(){
  ios_base::sync_with_stdio(0);
  //freopen("input.txt", r, stdin);
  //freopen("output.txt", w, stdout);
  cin >> n >> m >> x;
  g.resize(n+1);
  for (int i=0;i<=n;i++){
    g[i].resize(n+1);
  }
  for (int i=0;i<m;i++){
    cin >> a[i] >> b[i] >> c[i];
  }
  long double l = 0.0, r = 1000001.0;
  for (int i=0;i<228;i++){
    long double mid = (l + r) * 0.5;
    if (check(mid)) l = mid;
    else r = mid;
  }
  cout << fixed << setprecision(10) << l * x << endl;
}


#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define ll long long

using namespace std;

const ll inf = 1e18;
const int mod = 1e9 + 7;

long double a[505], b[505], c[505];
vector <int> used(51);
vector <vector <int> > g;
int n,m,x;

int dfs(int v, int pushed){
  if (v == n) return pushed;
  int flow = 0;
  used[v] = 1;
  for (int i=1;i<=n;i++){
    if (!used[i]  && g[v][i]){
      int cur = dfs(i, min(pushed,g[v][i]));
      flow += cur;
      pushed -= cur;
      g[v][i] -= cur;
      g[i][v] += cur;
    }
  }
  return flow;
}

int maxflow(){
  int flow = 0;
  //used.resize(n);
  used.assign(n,0);
  int add = dfs(1,1e9);
  while (add){
    flow += add;
    used.assign(n,0);
    add = dfs(1,1e9);
  }
  return flow;
}

bool check(long double k){
  for (int i=0;i<m;i++){
    g[a[i]][b[i]] = floor(c[i] / k);
  }
  if (maxflow() >= x)  return true;
  return false;
}

int main(){
  ios_base::sync_with_stdio(0);
  //freopen("input.txt", r, stdin);
  //freopen("output.txt", w, stdout);
  cin >> n >> m >> x;
  g.resize(n+1);
  for (int i=0;i<=n;i++){
    g[i].resize(n+1);
  }
  for (int i=0;i<m;i++){
    cin >> a[i] >> b[i] >> c[i];
  }
  long double l = 0.0, r = 1000001.0;
  for (int i=0;i<12228;i++){
    long double mid = (l + r) * 0.5;
    if (check(mid)) l = mid;
    else r = mid;
  }
  cout << fixed << setprecision(10) << l * x << endl;
}


#include <bits/stdc++.h>

#define F first
#define S second
#define pb push_back
#define ll long long

using namespace std;

const ll inf = 1e18;
const int mod = 1e9 + 7;

long double a[505], b[505], c[505];
vector <int> used(51);
vector <vector <int> > g;
int n,m,x;

int dfs(int v, int pushed){
  if (v == n) return pushed;
  int flow = 0;
  used[v] = 1;
  for (int i=1;i<=n;i++){
    if (!used[i]  && g[v][i]){
      int cur = dfs(i, min(pushed,g[v][i]));
      flow += cur;
      pushed -= cur;
      g[v][i] -= cur;
      g[i][v] += cur;
    }
  }
  return flow;
}

int maxflow(){
  int flow = 0;
  //used.resize(n);
  used.assign(n,0);
  int add = dfs(1,1e9);
  while (add){
    flow += add;
    used.assign(n,0);
    add = dfs(1,1e9);
  }
  return flow;
}

bool check(long double k){
  for (int i=0;i<m;i++){
    g[a[i]][b[i]] = floor(c[i] / k);
  }
  if (maxflow() >= x)  return true;
  return false;
}

int main(){
  ios_base::sync_with_stdio(0);
  //freopen("input.txt", r, stdin);
  //freopen("output.txt", w, stdout);
  cin >> n >> m >> x;
  g.resize(n+1);
  for (int i=0;i<=n;i++){
    g[i].resize(n+1);
  }
  for (int i=0;i<m;i++){
    cin >> a[i] >> b[i] >> c[i];
  }
  long double l = 0.0, r = 1000001.0;
  for (int i=0;i<150;i++){
    long double mid = (l + r) * 0.5;
    if (check(mid)) l = mid;
    else r = mid;
  }
  cout << fixed << setprecision(10) << l * x << endl;
}